2012-12-16 19 views
7

Xét đoạn mã sau:Việc liên kết tạm thời với một tham chiếu có yêu cầu một hàm tạo bản sao trong C++ không?

class A { 
    A(const A&); 
public: 
    A() {} 
}; 

int main() { 
    const A &a = A(); 
} 

Mã này biên dịch tốt với GCC 4.7.2, nhưng thất bại trong việc biên dịch với Visual C++ 2010 với các lỗi sau:

test.cc(8) : error C2248: 'A::A' : cannot access private member declared in class 'A' 
     test.cc(2) : see declaration of 'A::A' 
     test.cc(1) : see declaration of 'A' 

Vậy là nó cần thiết để có một constructor sao chép có thể truy cập khi liên kết một tạm thời với một tham chiếu?

này có phần liên quan đến câu hỏi trước đây của tôi:

Is there a way to disable binding a temporary to a const reference?

+0

Có, bản sao ctor là riêng tư và không được triển khai cố ý. – vitaut

+0

Bạn đã thử chỉ 'A(). 'Có thể nó cần hàm tạo bản sao để sao chép từ bên trong hàm đến giá trị trả về. –

+0

Visual C++ 2012 chấp nhận mã. –

Trả lời

4

So is it necessary to have a copy constructor accessible when binding a temporary to a reference?

Đăng C++ 11 - Không
Trước C++ 11 - Có.


Mã này biên dịch tốt với GCC 4.7.2 vì mã này tuân thủ tiêu chuẩn C++ 11.

C++ 11 tiêu chuẩn bắt buộc rằng khi tham chiếu const được khởi tạo từ prvalue, nó phải được ràng buộc trực tiếp với đối tượng tham chiếu và không có phép tạm thời được phép tạo. Ngoài ra, hàm tạo bản sao không được sử dụng hoặc được yêu cầu.

Trước C++ 11, các quy tắc khác nhau. Và hành vi này (cho dù nhà xây dựng bản sao sẽ được gọi là) được thực hiện được xác định hay chưa. C++ 03 cho phép hàm tạo bản sao được gọi trong khi ràng buộc một tham chiếu const tới một tạm thời và do đó đăng C++ 11, hàm tạo bản sao cần phải truy cập được. Visual C++ 2010 tuân thủ tiêu chuẩn C++ 03.

+0

"Và hành vi này đã được thực hiện được xác định" là một chút gây hiểu lầm. Việc sao chép thực tế hoặc không được thực hiện được xác định, nhưng tiêu chuẩn C++ 03 yêu cầu một hàm tạo bản sao có thể truy cập. –

+0

@ Cheersandhth.-Alf: Được chỉnh sửa để làm cho nó rõ ràng hơn. –

+1

"C++ 11 tiêu chuẩn bắt buộc rằng khi tham chiếu const được khởi tạo từ giá trị trước, nó phải được ràng buộc trực tiếp với đối tượng tham chiếu và không cho phép tạo tạm thời." chúng tôi một chút sai lầm. Nó chỉ nắm giữ khi các loại như vậy mà ràng buộc trực tiếp là có thể. Nói cách khác, các quy tắc không loại trừ một chuyển đổi. –

0

Visual C++ là không chính xác; tiêu chuẩn không chỉ ra rằng các nhà xây dựng bản sao phải có thể truy cập để ràng buộc một tham chiếu const tạm thời.

2

Mục 8.5.3.5 của các trạng thái tiêu chuẩn C++ 03 rằng đây là thực hiện xác định:

If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2," the reference is bound in one of the following ways (the choice is implementation-defined):

-- The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.

-- A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.

The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

Vì vậy, có vẻ như cả hai triển khai phù hợp với các tiêu chuẩn C++ 03.

Câu cuối cùng hơi khó hiểu, nhưng cách tôi đọc nó, điều đó có nghĩa là việc triển khai có thể chọn cách thứ hai, nhưng vẫn tối ưu hóa bản sao. Trong trường hợp đó, hàm tạo bản sao sẽ phải truy cập được ngay cả khi bản sao không thực sự được thực hiện, tương tự như tối ưu hóa giá trị trả lại.

Với tiêu chuẩn C++ 11, cách thứ hai không còn là tùy chọn nữa.

+4

C++ 03 đã bị thay thế bởi C++ 11 và các quy tắc đã thay đổi trong C++ 11. –

+0

Đúng, đó là những gì tôi đang tìm kiếm. Cảm ơn. – vitaut

+0

@Vaughn Cato: điều duy nhất là tuyên bố cuối cùng của bạn mâu thuẫn với tuyên bố cuối cùng từ tiêu chuẩn mà bạn trích dẫn. IIUC tiêu chuẩn nói rằng các ctor sao chép nên có sẵn trong cả hai trường hợp, do đó GCC có thể sử dụng các quy tắc từ tiêu chuẩn mới hoặc một lỗi của nó. – vitaut