2011-01-19 30 views
22

Tôi đang truyền một đối tượng tạm thời chưa được đặt tên cho một hàm được xác định với tham số const ref. Ctor bản sao của lớp là riêng tư, và tôi nhận được một lỗi biên dịch. Tôi không hiểu tại sao một nhà xây dựng bản sao được gọi trong tình huống này.lý do tại sao sao chép constructor được gọi là khi đi qua tạm thời bởi tham chiếu const?

class A { 
public: 
    A(int i) {} 
private: 
    A(const A&) {} 
}; 

void f(const A& a) 
{ 
} 

int main() 
{ 
    f(A(1)); // <-- error here: 'A::A(const A&)' is private 
} 

Đúng như dự đoán, khi tôi thay đổi chính:

A a(1); 
f(a); 

nó hoạt động.

EDIT: trình biên dịch là gcc 4.1.2

+0

Bạn đang sử dụng trình biên dịch nào? – sharptooth

+0

VC++ 9 rất vui khi biên dịch biến thể đầu tiên. – sharptooth

+0

@sharptooth: gcc, tôi sẽ cập nhật – davka

Trả lời

17

Bạn có thể tìm thấy câu trả lời cho câu hỏi của bạn trong Copy Constructor Needed with temp object hoặc đi trực tiếp vào http://gcc.gnu.org/bugs/#cxx%5Frvalbind

CáC++ Chuẩn C nói rằng một đối tượng tạm thời nên được tạo ra trong bối cảnh này và nội dung của nó làm đầy với một bản sao của đối tượng chúng tôi đang cố gắng để liên kết với tham chiếu; nó cũng cho biết rằng bản sao tạm thời có thể được elided, nhưng các hạn chế ngữ nghĩa (ví dụ: khả năng truy cập) của người tạo bản sao vẫn phải được kiểm tra.

Để biết thêm thông tin, bạn có thể tham khảo ý kiến ​​ đoạn văn sau đây của tiêu chuẩn C++: [dcl.init.ref]/5, đạn 2, tiểu đạn 1, và [class.temporary]/2.

Bắt đầu với GCC 4.3.0, GCC không còn đưa ra lỗi cho trường hợp này.Sự thay đổi này là dựa trên ý định của ủy ban ngôn ngữ C++ . Kể từ 2010-05-28, bản dự thảo cuối cùng được đề xuất của tiêu chuẩn C++ 0x cho phép mã này không có lỗi.

+2

+1 để có thông tin tốt! – Nawaz

0

Bởi vì một (1) gọi constructor A (int i) và sau đó A (const Một &) được gọi trong các cuộc gọi để làm mất hiệu lực f (const Một &).

Làm cho hàm tạo A (int i) rõ ràng và bạn không nên gặp phải lỗi này.

Chỉnh sửa: Tôi nghĩ rằng tôi đã hiểu nhầm câu hỏi. Tôi có thể xóa cái này.

+0

** Từ tiêu chuẩn C++ §3.2 đoạn 2 : ** Một hàm tạo bản sao được sử dụng ngay cả khi cuộc gọi thực sự được ưu tiên bởi triển khai . – dalle

+2

Các nhà xây dựng bản sao nên khái niệm không được gọi ở đây, đó là điểm của câu hỏi. Đi qua tham chiếu ngụ ý không tạo ra một đối tượng mới, do đó không có bản sao. – sharptooth

+0

Tại sao bỏ phiếu xuống? Nó thực sự là chính xác, theo tiêu chuẩn. – dalle

18

Biểu thức A(1)rvalue 5.2.3 [expr.type.conv].

Trong khởi tạo một tài liệu tham khảo const (đối số chức năng) với một biểu hiện đó là một rvalue trình biên dịch thể tạo tạm thời và sao chép giá trị của biểu thức đó để tạm thời và ràng buộc mà tham chiếu đến mà tạm thời. 8.5.3 [dcl.init.ref]/5.

[...] Hàm tạo sẽ được gọi cho dù bản sao có thực sự được thực hiện hay không.

Lưu ý rằng hành vi này là do thay đổi trong phiên bản tiếp theo của C++. Trong tiêu chuẩn mới, tham chiếu const được khởi tạo từ một lớp prvalue phải được ràng buộc trực tiếp với đối tượng tham chiếu; không được phép tạo tạm thời trong trường hợp này và một hàm tạo bản sao không được sử dụng hoặc được yêu cầu.

+0

+1 cho chính xác! – Nawaz

+0

cảm ơn. đoạn cuối cùng của bạn giải thích lý do tại sao điều này không xảy ra trong phiên bản gcc mới hơn theo nhận xét @Nawaz, đúng không? – davka

+0

@davka: Tôi tin rằng đó là lý do, vâng. –

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