2012-12-14 4 views
6

g ++ 4.7 hỗ trợ khởi tạo thành viên mảng và tôi bắt đầu chơi với nó.khởi tạo thành viên mảng của người dùng xác định loại

Mã bên dưới không biên dịch.

struct A 
{ 
    A(int){}; 
    A(const A&) = delete; 
    A& operator=(const A&) = delete; 
    ~A(){}; 
}; 

struct B 
{ 
    B(): 
     a{{0},{1}} 
    {}; 
    A a[2]; 
}; 

B b; 

Các thông báo lỗi với gcc 4.8 (phát hành trước) là:

n.cc: In constructor ‘B::B()’: 
n.cc:12:20: error: use of deleted function ‘A::A(const A&)’ 
      a{{0},{1}} 
      ^
n.cc:4:8: error: declared here 
     A(const A&) = delete; 
     ^

Có cách nào để làm cho công việc mã này? Tôi không thể dễ dàng thay đổi các contructors, destructor của A. Tôi dường như cần một di chuyển-constructor hoặc copy-constructor để khởi tạo mảng, nhưng điều này có vẻ phản trực giác, vì tất cả tôi thực sự muốn là tại chỗ xây dựng.

Nó hoạt động nếu tôi chia một [2] thành 2 thành viên a0 và a1 và tạo riêng chúng. Điều này có vẻ cá tanh.

+0

':' trong một hàm tạo sử dụng các hàm tạo bản sao để gán các giá trị và bạn xóa nó trong A do đó cho bạn một lỗi. –

Trả lời

2

Mảng là tập hợp và tổng hợp khởi tạo luôn sử dụng khởi tạo sao chép. C++ 11 §8.5.1/1:

Một tổng là một mảng hoặc một lớp học không có nhà xây dựng người dùng cung cấp, không có cú đúp-hoặc-bằng-initializer s cho phi các thành viên dữ liệu tĩnh, không có thành viên dữ liệu không bảo mật hoặc riêng tư, không có lớp cơ sở và không có chức năng ảo.

§8.5.1/2:

Khi một tổng thể được khởi tạo bởi một danh sách initializer, theo quy định tại 8.5.4, các yếu tố của danh sách initializer được thực hiện như initializers cho các thành viên của tổng hợp, khi tăng chỉ số hoặc thành viên. Mỗi thành viên được sao chép-khởi tạo từ điều khoản khởi tạo tương ứng. & hellip;

(tôi nhấn mạnh).

Bên cạnh đó, trình biên dịch không ngầm tạo ra một constructor chuyển nếu một người dùng tuyên bố constructor sao chép hiện diện (§12.8/9); bởi vì bạn có một hàm tạo bản sao do người dùng khai báo được định nghĩa là đã xóa, A không có bản sao cũng như một hàm tạo di chuyển. Một cách rõ ràng thêm một constructor di chuyển các công trình:

struct A 
{ 
    A(int) { } 
    A(A const&) = delete; 
    A& operator = (A const&) = delete; 
    A(A&&) = default; 
    ~A() = default; 
}; 

struct B 
{ 
    B() : a{{0}, {1}} { } 
    A a[2]; 
}; 

int main() 
{ 
    B b; 
} 

Online demo

này là về càng gần với những gì bạn muốn như bạn đang đi để có được.

+0

Không phải là câu trả lời tôi đã hy vọng, nhưng cảm ơn lời giải thích chi tiết. – mirk

4

Trong vòng danh sách khởi tạo (8.5.4p1) của tổng hợp (8.5.1), hình thức khởi tạo được thực hiện trên các phần tử tổng hợp là khởi tạo sao chép (8.5.1p2), ngay cả khi khởi tạo là trực tiếp-list-khởi:

Khi một tổng thể được khởi tạo bởi một danh sách initializer, như speci ed fi trong 8.5.4, các yếu tố của danh sách initializer được thực hiện như initializers cho các thành viên của tổng hợp, trong việc tăng chỉ số hoặc thành viên.Mỗi thành viên được sao chép-khởi tạo từ điều khoản khởi tạo tương ứng.

Tuy nhiên, chỉ vì hình thức khởi tạo được thực hiện là khởi tạo sao chép không có nghĩa là một bản sao xảy ra. Theo số copy-list-initialization of non-copyable types, sao chép danh sách-bản sao phải giống hệt với bắt đầu danh sách trực tiếp ngoại trừ các nhà thầu rõ ràng không được phép.