Khởi tạo mảng thành viên trong bộ khởi tạo hàm tạo


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

Tôi tin rằng lý do là các mảng chỉ có thể được khởi tạo bằng =cú pháp, đó là:

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

Câu hỏi

  1. Làm cách nào tôi có thể làm những gì tôi muốn (nghĩa là khởi tạo một mảng trong một phương thức khởi tạo (không gán các phần tử trong phần thân)). Nó thậm chí có thể?
  2. Tiêu chuẩn C ++ 03 có nói gì đặc biệt về việc khởi tạo tổng hợp (bao gồm mảng) trong trình khởi tạo ctor không? Hay sự không hợp lệ của đoạn mã trên là hệ quả của một số quy tắc khác?
  3. Danh sách trình khởi tạo C ++ 0x có giải quyết được vấn đề không?

PS Vui lòng không đề cập đến các vectơ, boost :: array và tính ưu việt của chúng so với mảng mà tôi biết rõ.


Bạn cũng biết về sự tồn tại của các mảng kích thước cố định boost, cung cấp các hàm tạo?
Benoît

2
@ Benoît: Đúng vậy. Nhưng tôi cần biết về mảng đồng bằng :)
Armen Tsirunyan

Câu trả lời:


55
  1. Làm cách nào tôi có thể làm những gì tôi muốn (nghĩa là khởi tạo một mảng trong một phương thức khởi tạo (không gán các phần tử trong phần thân)). Nó thậm chí có thể?

Đúng. Nó sử dụng một cấu trúc chứa một mảng. Bạn nói rằng bạn đã biết về điều đó, nhưng sau đó tôi không hiểu câu hỏi. Bằng cách đó, bạn làm khởi tạo một mảng trong các nhà xây dựng, mà không tập trong cơ thể. Đây là những gì boost::arrayhiện.

Tiêu chuẩn C ++ 03 có nói gì đặc biệt về việc khởi tạo tổng hợp (bao gồm mảng) trong trình khởi tạo ctor không? Hay sự không hợp lệ của đoạn mã trên là hệ quả của một số quy tắc khác?

Trình khởi tạo ghi nhớ sử dụng khởi tạo trực tiếp. Và các quy định của khoản 8 cấm loại điều này. Tôi không chắc chắn chính xác về trường hợp sau, nhưng một số trình biên dịch cho phép điều đó.

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

Xem GCC PR này để biết thêm chi tiết.

Danh sách trình khởi tạo C ++ 0x có giải quyết được vấn đề không?

Có, họ có. Tuy nhiên, cú pháp của bạn không hợp lệ, tôi nghĩ. Bạn phải sử dụng dấu ngoặc nhọn trực tiếp để kích hoạt khởi tạo danh sách

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

Tôi tình cờ về điều này khi tôi viết: char * const foo[6];thành viên trong lớp. Nó yêu cầu trình khởi tạo để biên dịch trong C ++ 11.
JATothrim 13/09/18

33

C ++ 98 không cung cấp cú pháp trực tiếp cho bất kỳ thứ gì ngoài việc làm 0 (hoặc cho các phần tử không phải POD, khởi tạo giá trị) mảng. Đối với điều đó bạn chỉ cần viết C(): arr() {}.

Tôi điều Roger Pate đã sai về những hạn chế bị cáo buộc của việc khởi tạo tổng hợp C ++ 0x, nhưng tôi quá lười để tra cứu hoặc kiểm tra nó, và nó không quan trọng, phải không? CHỈNH SỬA : Roger đã nói về "C ++ 03", tôi đã đọc nhầm thành "C ++ 0x". Xin lỗi, Roger. ☺

Một giải pháp C ++ 98 cho mã hiện tại của bạn là bao bọc mảng trong một structvà khởi tạo nó từ một hằng số tĩnh của kiểu đó. Dữ liệu phải nằm ở đâu đó. Nó có thể trông như thế này:

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}};

Tôi đã nói 0x có những hạn chế nào?

@Roger: "khởi tạo agrregate ... không vừa với trình khởi tạo ctor". Chỉ cần kiểm tra bản nháp C ++ 0x N3126, cú pháp của bộ khởi tạo ghi nhớ , trong §12.5.2 / 1, bao gồm việc sử dụng danh sách giằng-init .
Chúc mừng và hth. - Alf

6
Hai từ đầu tiên của câu của tôi là Trong C ++ 03, ...

8

Cách giải quyết:

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. Không, thật không may.
  2. Bạn chỉ không thể theo cách bạn muốn, vì nó không được ngữ pháp cho phép (thêm bên dưới). Bạn chỉ có thể sử dụng khởi tạo giống ctor và như bạn đã biết, tính năng này không khả dụng để khởi tạo từng mục trong mảng.
  3. Tôi tin như vậy, vì họ khái quát quá trình khởi tạo trên bảng theo nhiều cách hữu ích. Nhưng tôi không chắc về các chi tiết.

Trong C ++ 03, khởi tạo tổng hợp chỉ áp dụng với cú pháp tương tự như bên dưới, đây phải là một câu lệnh riêng biệt và không phù hợp với trình khởi tạo ctor.

T var = {...};

2

Làm thế nào về

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

?

Biên dịch tốt trên g ++ 4.8


Đây có phải là tiêu chuẩn? Bạn có thể trích dẫn điều khoản liên quan, xin vui lòng?
Armen Tsirunyan

2
Không biên dịch trên Visual C ++.
sergiol

-2

Bạn muốn init một mảng int trong hàm tạo của bạn? Trỏ nó vào một mảng tĩnh.

class C 
{
public:
    int *cArray;

};

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

2
Đây là một ý tưởng tồi, bởi vì nếu bạn thay đổi mảng đó, nó sẽ thay đổi cho tất cả các trường hợp của lớp đó.
morty
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.