10

Đây chỉ là một câu hỏi nhanh chóng để hiểu một cách chính xác những gì sẽ xảy ra khi bạn tạo ra một lớp với một constructor như thế này:trình biên dịch tạo nhà xây dựng

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

Tôi biết rằng không có constructor mặc định được tạo ra vì nó đã được xác định nhưng các hàm tạo bản sao và gán được tạo bởi trình biên dịch hoặc nói cách khác là tôi cần phải khai báo một hàm tạo bản sao riêng và toán tử gán riêng để ngăn điều này xảy ra?

class A 
{ 
    private: 
    // needed to prevent automatic generation? 
    A(const A&); 
    A& operator=(const A&); 
    public: 
    A() {} 
}; 

Trả lời

10

Có. Trình tạo bản sao, toán tử gán và hàm hủy luôn được tạo bất kể các hàm tạo và toán tử khác.

Nếu bạn muốn tắt một ứng dụng, những gì bạn có ở đó là hoàn hảo. Nó khá phổ biến.

+0

Trên thực tế, mặc dù nếu bạn đang sử dụng này để ngăn chặn sao chép/chuyển nhượng, kiểm tra [tăng :: noncopyable] (http: // www .boost.org/doc/libs/1_55_0/libs/utility/utility.htm # Class_noncopyable). (Bạn có thể tách ra lớp đơn giản này hoặc viết của riêng bạn và tái sử dụng nó bất cứ nơi nào bạn muốn.) – TypeIA

13

Có, sao chép hàm tạo và sao chép toán tử gán vẫn được tạo ngay cả khi bạn khai báo hàm tạo mặc định của riêng bạn.

Việc tạo ra chúng chỉ bị chặn nếu bạn khai báo hàm tạo bản sao của riêng bạn hoặc sao chép toán tử gán trong định nghĩa lớp tương ứng.

Lưu ý rằng nó có thể có cả hai constructor sao chép của riêng bạn, và một trình biên dịch cung cấp một:

struct A { 
    A() { } 
    A(A const&, int foo); 
}; // compiler declares a copy constructor now 

// make the second parameter have a default argument 
// now this constructor is a copy constructor too. 
inline A::A(A const&, int foo = 0) { 

} 

int main() { 
    A a; 
    A b = a; // ambiguity between compiler's one and our custom one! 
} 

tuy nhiên Tiêu chuẩn cho phép trình biên dịch để chấp nhận mã này - nhưng hiệu quả tương tự như có hành vi undefined: Chương trình bị lỗi, nhưng không cần cảnh báo/lỗi cho chương trình đó. (các phiên bản GCC đầu tiên không từ chối mã này, các phiên bản gần đây từ chối nó).

+1

Bài viết của bạn là "như thường lệ" rất nhiều thông tin :) –

2

Nếu bạn muốn vô hiệu hóa sao chép và gán, có thể tốt hơn để kế thừa từ một lớp có hàm tạo bản sao riêng và toán tử gán (boost::noncopyable là một trình sẵn sàng).

1) Nhập ít lặp đi lặp lại.

2) Tự ghi tài liệu (hy vọng).

3) Kiểm tra mạnh mẽ hơn rằng các thao tác đó không thể được gọi (chính lớp đó, cũng như bạn bè cũng có thể tạo bản sao - điều đó sẽ dẫn đến trình biên dịch chứ không phải lỗi liên kết).

4) Sẽ không giấu constructor mặc định :)

#include <boost/noncopyable.hpp> 

class X : boost::noncopyable 
{ 
}; 

int main() 
{ 
    X a, b;  //has default constructor 
    //X c(a); //but can't be copied 
    //a = b; //or assigned 
} 
Các vấn đề liên quan