2011-11-21 19 views
14

Theo N2628 liên quan đến , trình khởi tạo thành viên dữ liệu không tĩnh có thể bị ghi đè bởi các hàm tạo được xác định rõ ràng, nhưng có vẻ hơi mơ hồ về hàm tạo bản sao được xác định ngầm.Trong C++ 0x, các bộ khởi tạo thành viên dữ liệu không tĩnh có ghi đè lên hàm tạo bản sao ngầm không?

Đặc biệt, tôi đã nhận thấy rằng với phiên bản Apple clang 3.0, hành vi khác nhau tùy thuộc vào việc cấu trúc (hay lớp) là một POD.

Chương trình sau trả về đầu ra "1", cho biết rằng hàm tạo bản sao bỏ qua phía bên tay phải và thay thế trình khởi tạo thành viên dữ liệu không tĩnh mới (trong ví dụ này, giá trị true boolean cho X :: a).

#include <iostream> 
#include <string> 

struct X 
{ 
    std::string string1; 
    bool a = true; 
}; 

int main(int argc, char *argv[]) 
{ 
    X x; 
    x.a = false; 
    X y(x); 
    std::cout << y.a << std::endl; 
} 

Tuy nhiên, gây nhầm lẫn, nếu bạn nhận xét ra chuỗi1:

// std::string string1; 

sau đó hành vi hoạt động như tôi mong đợi (đầu ra là "0"), có lẽ vì không có mặc nhiên tạo sao chép constructor và do đó dữ liệu được sao chép.

Đặc tả C++ 0x có thực sự khuyên bạn nên cho phép hàm tạo bản sao được xác định rõ ràng để không phải là sao chép nội dung của phía bên tay phải không? Đó không phải là ít hữu ích và không trực quan? Tôi thấy chức năng khởi tạo thành viên không tĩnh khá thuận tiện, nhưng nếu đây là hành vi đúng, thì tôi sẽ tránh tính năng này một cách rõ ràng do hành vi khôn lanh và không trực quan của nó.

Vui lòng cho tôi biết tôi sai?

CẬP NHẬT: Lỗi này đã được sửa trong kho lưu trữ nguồn Clang. Xem này revision.

CẬP NHẬT: Lỗi này xuất hiện cố định trong phiên bản Apple clang 3.1 (thẻ/Apple/clang-318.0.45) (dựa trên LLVM 3.1svn). Phiên bản này của clang được phân phối như một phần của Xcode 4.3 cho Lion.

+0

+1 cho nebulosity –

Trả lời

10

Nó không phải là bóng tối sau khi tất cả, xem các phần nhấn mạnh các tiêu chuẩn trích đoạn:

Phần trên constructor sao chép/di chuyển defaulted (§ 12,8) là một chút quá dài để trích dẫn trong đó là toàn bộ. Các xuống thấp là trường thành viên không tĩnh với initializers vẫn chỉ đơn giản là sao chép bởi các defaulted sao chép/di chuyển constructor

§ 12,8:

-6. Trình xây dựng sao chép/di chuyển được xác định ngầm cho một lớp không phải là công đoàn X thực hiện sao chép/di chuyển thành viên các cơ sở và thành viên của nó. [ Note: brace-or-equal-initializers of non-static data members are ignored. See also the example in 12.6.2. —end note ] Thứ tự khởi tạo giống như thứ tự khởi tạo của các cơ sở và thành viên trong một hàm tạo do người dùng xác định (xem 12.6.2). Cho x là tham số của hàm tạo hoặc đối với hàm tạo di chuyển, tham số x tham chiếu đến tham số.Mỗi cơ sở hoặc không tĩnh dữ liệu thành viên được sao chép/di chuyển theo cách thức phù hợp với loại của nó:

  • nếu hội viên là một mảng, mỗi phần tử là trực tiếp khởi tạo với các subobject tương ứng của x;
  • nếu một thành viên m có loại tham chiếu rvalue T & &, nó được khởi tạo trực tiếp với static_cast (x.m);
  • nếu không, cơ sở hoặc thành viên được khởi tạo trực tiếp với cơ sở hoặc thành viên tương ứng của x.
    ảo subobjects lớp cơ sở sẽ được khởi tạo một lần duy nhất bởi các nhà xây dựng sao chép/di chuyển ngầm xác định

này được mẫu gọi:

struct A { 
    int i = /* some integer expression with side effects */; 
    A(int arg) : i(arg) { } 
    // ... 
}; 

A (int) constructor sẽ đơn giản khởi tạo i với giá trị của arg, và các hiệu ứng phụ trong dấu ngoặc đơn hoặc đồng đẳng của i sẽ không xảy ra. —end example ]


Để hoàn chỉnh, phần tương ứng trên constructor mặc định defaulted:

§ 12,1

-6. Một hàm tạo mặc định được mặc định và không được định nghĩa là đã xóa được định nghĩa hoàn toàn khi được sử dụng odr-sử dụng (3.2) để tạo đối tượng thuộc loại lớp (1.8) hoặc khi được mặc định rõ ràng sau khai báo đầu tiên.
Hàm tạo mặc định ngầm định thực hiện bộ khởi tạo của lớp sẽ được thực hiện bởi hàm tạo mặc định do người dùng viết cho lớp đó không có bộ khởi tạo ctor (12.6.2) và hợp chất trống. Nếu hàm tạo mặc định do người dùng viết đó sẽ bị hỏng, chương trình sẽ không được định dạng.
Nếu hàm tạo mặc định do người dùng viết sẽ đáp ứng các yêu cầu của một hàm tạo constexpr (7.1.5), thì hàm tạo mặc định ngầm định là constexpr. Trước khi hàm dựng mặc định mặc định cho lớp được định nghĩa hoàn toàn, tất cả các hàm tạo mặc định không do người dùng cung cấp cho các lớp cơ sở của nó và các thành viên dữ liệu không tĩnh của nó phải được xác định hoàn toàn. [Lưu ý: Một hàm tạo mặc định được khai báo ngầm có một đặc tả ngoại lệ (15.4).
Định nghĩa mặc định rõ ràng có thể có một đặc tả ngoại lệ ẩn, xem 8.4. —end note ]

+0

Thú vị. Đây có phải là tham chiếu đến _copy-constructor_ mặc định không? –

+0

Điều này dường như chỉ đề cập đến hàm tạo mặc định, AFAIK là hàm tạo dùng 0 đối số. – Kleist

+0

Tài liệu tham khảo này nói về * constructor mặc định * không phải là * copy constructor * –

Các vấn đề liên quan