2013-06-20 40 views
20

Mã này:Tại sao tôi không được cung cấp một hàm tạo bản sao mặc định từ một biến động?

class X { 
    int member; 
}; 

volatile X a; 
X b = a; 

Không với các lỗi:

prog.cpp:6:7: error: no matching function for call to ‘X::X(volatile X&)’ 
prog.cpp:6:7: note: candidates are: 
prog.cpp:1:7: note: X::X() 
prog.cpp:1:7: note: candidate expects 0 arguments, 1 provided 
prog.cpp:1:7: note: X::X(const X&) 
prog.cpp:1:7: note: no known conversion for argument 1 from ‘volatile X’ to ‘const X&’ 

Có cách nào tôi có thể nhận được biên dịch để tạo ra một constructor sao chép bất ổn đối với tôi?

+0

Bạn cần để khai báo 'b'as' volatile'. – 0x499602D2

+0

Nhưng tôi muốn có một bản sao không dễ bay hơi! – Eric

+3

'volatile X &' không thể được chuyển đổi thành 'const X &' bởi vì hai giá trị mâu thuẫn nhau: 'const' nói" đọc nó một lần, nó sẽ không thay đổi ", trong khi' volatile' nói "đọc nó mọi lúc, bởi vì nó có thể thay đổi". Phải có một số quy tắc thông minh trong tiêu chuẩn C++ cấm thực hiện chuyển đổi này một cách ngầm định. – dasblinkenlight

Trả lời

14

Câu trả lời ngắn gọn là: Vì tiêu chuẩn cho biết bạn sẽ không làm như vậy.

Tiêu chuẩn C++ 12.8/9 (Dự thảo N3242) cho:

The implicitly-declared copy constructor for a class X will have the form

  • X::X(const X&)

if

  • each direct or virtual base class B of X has a copy constructor whose first parameter is of type const B& or const volatile B&, and
  • for all the non-static data members of X that are of a class type M (or array thereof), each such class type has a copy constructor whose first parameter is of type const M& or const volatile M&. [Note: 119]

Otherwise, the implicitly-declared copy constructor will have the form

  • X::X(X&)

Note 119 nói:

This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue; see C.1.9.

Trong C.1.9 bạn sẽ tìm thấy:

The implicitly-declared copy constructor and implicitly-declared copy assignment operator cannot make a copy of a volatile lvalue. For example, the following is valid in ISO C:

struct X { int i; }; 
volatile struct X x1 = {0}; 
struct X x2(x1); // invalid C++ 
struct X x3; 
x3 = x1; // also invalid C++ 

Rationale: Several alternatives were debated at length. Changing the parameter to volatile const X& would greatly complicate the generation of efficient code for class objects. Discussion of providing two alternative signatures for these implicitly-defined operations raised unanswered concerns about creating ambiguities and complicating the rules that specify the formation of these operators according to the bases and members.

-3

Vấn đề chính là bạn không cung cấp hàm tạo gán. Do đó, trình biên dịch tạo ra một mặc định một cho bạn: constructor phân

X& X::operator =(const X& x){ 
    this.member = x.member; 
    return *this; 
} 

Giá trị mặc định chấp nhận kiểu lập luận như const X & trong đó const là một ở mức độ thấp const và chiến thắng' không được bỏ qua là cấp cao nhất const.

Mã của bạn X b = a có nghĩa là gọi hàm tạo mặc định. Nhưng lập luận của bạn a có kiểu dễ bay hơi X (có thể được chuyển đổi sang dễ bay hơi X &const dễ bay hơi X &) không thể được chuyển đổi sang const X & ngầm.

Vì vậy, bạn cần xác định xây dựng nhiệm vụ của riêng bạn như

X& X::operator =(volatile const X&); 

EDIT
Nó gây sốc cho tôi rằng rất nhiều chàng trai nghĩ rằng copy constructor (hoặc gọi bản sao khởi) là được gọi khi sử dụng nhà điều hành chuyển nhượng . Có thể gọi nó là nhà điều hành gán không phổ biến. Tuy nhiên, những gì tôi quan tâm là phương pháp nào được gọi.

Bạn có thể tham khảo bài này: Copy constructors, assignment operators, and exception safe assignmentDefault assignment operator


EDIT
Tôi đã phạm sai lầm trước đó. X b = a chỉ là quá trình khởi tạo. Không có nhiệm vụ được tham gia. Xin lỗi cho thông báo lỗi của tôi.

+3

Không. Một hàm tạo như 'X (biến động const X & x): thành viên (x.member) {}' sẽ được yêu cầu vì 'X b = a;' là khởi tạo sao chép. Không có thứ như "constructor chuyển nhượng". Có hoặc là một hàm tạo hoặc một toán tử gán. – Pixelchemist

+0

@Pixelchemist Những gì bạn cung cấp được gọi là "copy constructor". Hai thứ này là những thứ khác nhau. Nó được gọi là ** quy tắc của ba ** trong C++. – Zachary

+0

Quy tắc ba chủ yếu áp dụng cho các lớp quản lý tài nguyên. Trong trường hợp này, một hàm tạo bản sao không rõ ràng được yêu cầu thực hiện chuyển đổi từ X biến động thành X. – Pixelchemist

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