การเริ่มต้นอาร์เรย์สมาชิกในตัวสร้างเริ่มต้น


100
class C 
{
public:
 C() : arr({1,2,3}) //doesn't compile
{}
    /*
    C() : arr{1,2,3} //doesn't compile either
{}
    */
private:
 int arr[3];
};

ฉันเชื่อว่าเหตุผลคืออาร์เรย์สามารถเริ่มต้นด้วย=ไวยากรณ์เท่านั้นนั่นคือ:

int arr[3] = {1,3,4};

คำถาม

  1. ฉันจะทำสิ่งที่ต้องการได้อย่างไร (นั่นคือเริ่มต้นอาร์เรย์ในตัวสร้าง (ไม่ได้กำหนดองค์ประกอบในเนื้อความ)) เป็นไปได้หรือไม่?
  2. มาตรฐาน C ++ 03 พูดอะไรเป็นพิเศษเกี่ยวกับการเริ่มต้นการรวม (รวมถึงอาร์เรย์) ใน ctor initializers หรือไม่ หรือความไม่ถูกต้องของรหัสข้างต้นเป็นข้อพิสูจน์ของกฎอื่น ๆ ?
  3. รายการเริ่มต้น C ++ 0x ช่วยแก้ปัญหาได้หรือไม่

ปล.โปรดอย่าพูดถึงเวกเตอร์, บูสต์ :: อาร์เรย์และความเหนือกว่าอาร์เรย์ซึ่งผมทราบดี


คุณยังทราบถึงการมีอยู่ของอาร์เรย์ขนาดคงที่ที่เพิ่มขึ้นซึ่งมีตัวสร้าง
Benoît

2
@ Benoît: ฉัน. แต่ฉันต้องรู้เกี่ยวกับอาร์เรย์ธรรมดา :)
Armen Tsirunyan

คำตอบ:


56
  1. ฉันจะทำสิ่งที่ต้องการได้อย่างไร (นั่นคือเริ่มต้นอาร์เรย์ในตัวสร้าง (ไม่ได้กำหนดองค์ประกอบในเนื้อความ)) เป็นไปได้หรือไม่?

ใช่. โดยใช้โครงสร้างที่มีอาร์เรย์ คุณบอกว่าคุณรู้เรื่องนั้นอยู่แล้ว แต่ฉันก็ไม่เข้าใจคำถาม ด้วยวิธีนี้คุณจะเริ่มต้นอาร์เรย์ในตัวสร้างโดยไม่มีการกำหนดในเนื้อความ นี่คือสิ่งที่boost::arrayทำ

มาตรฐาน C ++ 03 พูดอะไรเป็นพิเศษเกี่ยวกับการเริ่มต้นการรวม (รวมถึงอาร์เรย์) ใน ctor initializers หรือไม่ หรือความไม่ถูกต้องของรหัสข้างต้นเป็นข้อพิสูจน์ของกฎอื่น ๆ ?

mem-initializer ใช้การเริ่มต้นโดยตรง และกฎของข้อ 8 ห้ามเรื่องแบบนี้. ฉันไม่แน่ใจเกี่ยวกับกรณีต่อไปนี้ แต่คอมไพเลอร์บางตัวอนุญาต

struct A {
  char foo[6];
  A():foo("hello") { } /* valid? */
};

ดูGCC PR นี้สำหรับรายละเอียดเพิ่มเติม

รายการเริ่มต้น C ++ 0x ช่วยแก้ปัญหาได้หรือไม่

ใช่. อย่างไรก็ตามไวยากรณ์ของคุณไม่ถูกต้องฉันคิดว่า คุณต้องใช้วงเล็บปีกกาโดยตรงเพื่อปิดการเริ่มต้นรายการ

struct A {
  int foo[3];
  A():foo{1, 2, 3} { }
  A():foo({1, 2, 3}) { } /* invalid */
};

ฉันสะดุดกับเรื่องนี้เมื่อฉันเขียน: char * const foo[6];สมาชิกชั้นเรียน มันต้องมีการเริ่มต้นที่จะรวบรวมใน C ++ 11
JATothrim

33

C ++ 98 ไม่ได้จัดเตรียมไวยากรณ์โดยตรงสำหรับสิ่งใด ๆ นอกจากการทำให้เป็นศูนย์ (หรือสำหรับองค์ประกอบที่ไม่ใช่ POD การกำหนดค่าเริ่มต้น) อาร์เรย์ C(): arr() {}สำหรับสิ่งที่คุณเพียงแค่เขียน

ฉันคิดว่า Roger Pate ผิดเกี่ยวกับข้อ จำกัด ที่ถูกกล่าวหาของการเริ่มต้นรวม C ++ 0x แต่ฉันขี้เกียจเกินไปที่จะค้นหาหรือตรวจสอบและมันไม่สำคัญใช่ไหม แก้ไข : Roger กำลังพูดถึง "C ++ 03" ฉันเข้าใจผิดว่าเป็น "C ++ 0x" ขอโทษโรเจอร์ ☺

วิธีแก้ปัญหา C ++ 98 สำหรับโค้ดปัจจุบันของคุณคือการรวมอาร์เรย์ใน a structและเริ่มต้นจากค่าคงที่คงที่ของประเภทนั้น ข้อมูลจะต้องอยู่ที่ไหนสักแห่งอยู่ดี ปิดข้อมือจะมีลักษณะดังนี้:

class C 
{
public:
    C() : arr( arrData ) {}

private:
     struct Arr{ int elem[3]; };
     Arr arr;
     static Arr const arrData;
};

C::Arr const C::arrData = {{1, 2, 3}};

ฉันบอกว่า 0x มีข้อ จำกัด อะไรบ้าง?

@Roger: "agrregate initialization ... ไม่พอดีกับ ctor initializer" เพียงแค่การตรวจสอบ C ++ 0x ร่าง N3126 ไวยากรณ์ของการเป็นข่าว-initializerใน§12.5.2 / 1 รวมถึงการใช้ค้ำยัน-init รายการ
ไชโยและ hth - Alf

6
สองคำแรกของประโยคของฉันอยู่ใน C ++ 03, ...

8

วิธีแก้ปัญหา:

template<class T, size_t N>
struct simple_array { // like std::array in C++0x
   T arr[N];
};


class C : private simple_array<int, 3> 
{
      static simple_array<int, 3> myarr() {
           simple_array<int, 3> arr = {1,2,3};
           return arr;
      }
public:
      C() : simple_array<int, 3>(myarr()) {}
};

3
  1. ไม่น่าเสียดาย
  2. คุณทำไม่ได้ในแบบที่คุณต้องการเนื่องจากไวยากรณ์ไม่ได้รับอนุญาต (เพิ่มเติมด้านล่าง) คุณสามารถใช้การเริ่มต้นเหมือน ctor เท่านั้นและอย่างที่คุณทราบไม่มีให้ใช้สำหรับการเริ่มต้นแต่ละรายการในอาร์เรย์
  3. ฉันเชื่อเช่นนั้นในขณะที่พวกเขาสรุปการเริ่มต้นทั่วทั้งกระดานด้วยวิธีที่มีประโยชน์มากมาย แต่ฉันไม่แน่ใจในรายละเอียด

ใน C ++ 03 การเตรียมใช้งานแบบรวมจะใช้เฉพาะกับไวยากรณ์ที่คล้ายกันดังต่อไปนี้ซึ่งต้องเป็นคำสั่งแยกต่างหากและไม่พอดีกับตัวเริ่มต้น ctor

T var = {...};

2

เกี่ยวกับ

...
  C() : arr{ {1,2,3} }
{}
...

เหรอ?

รวบรวมได้ดีบน g ++ 4.8


เป็นมาตรฐานหรือไม่ คุณสามารถอ้างอิงประโยคที่เกี่ยวข้องได้ไหม
Armen Tsirunyan

2
ไม่รวบรวมบน Visual C ++
sergiol

-3

คุณต้องการเริ่มอาร์เรย์ของ ints ในตัวสร้างของคุณหรือไม่? ชี้ไปที่อาร์เรย์แบบคงที่

class C 
{
public:
    int *cArray;

};

C::C {
    static int c_init[]{1,2,3};
    cArray = c_init;
}

2
นี่เป็นความคิดที่ไม่ดีเพราะถ้าคุณเปลี่ยนอาร์เรย์นั้นจะเปลี่ยนไปสำหรับอินสแตนซ์ทั้งหมดของคลาสนั้น
มรรตัย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.