6

Ví dụ dưới đây, tôi ngạc nhiên khi thấy rằng mặc dù hàm khởi tạo mặc định bị xóa (hoặc được tạo mặc định cho vấn đề đó), vẫn có thể khởi tạo tổng hợp.Khởi tạo tổng hợp không duy trì quyền truy cập của hàm tạo

#include <iostream> 

struct DefaultPrivate 
{ 
     const int n_; 
     static const DefaultPrivate& create(); 

    private: 
     DefaultPrivate() = delete; 
}; 

const DefaultPrivate& DefaultPrivate::create() 
{ 
    static DefaultPrivate result{10}; 
    return result; 
} 

int main() { 
    DefaultPrivate x; //Fails 
    DefaultPrivate y{10};//Works 
    return 0; 
} 

Mối quan hệ giữa cấu hình mặc định riêng tư (hoặc đã xóa) và khởi tạo tổng hợp không được chỉ định trong tiêu chuẩn?

Đây là trường hợp trên cả hai GCC 6.3 và VCC 2017

Lý do tôi đặt ra câu hỏi, là tôi hy vọng rằng việc thay đổi quyền truy cập vào các nhà xây dựng mặc định sẽ ngăn chặn công tổng khởi

+0

Xin lỗi, tôi đã nhận thấy và sẽ xóa phần đó. Tôi đã sửa đổi tệp h và vì một lý do nào đó tệp cpp của tôi không biên dịch lại –

Trả lời

4

Từ C++ 11, cho list initialization,

Nếu loại tổng hợp, tổng hợp khởi tạo được thực hiện.

Và với C++ 11 một aggregate là một trong các loại sau đây:

...

lớp kiểu (thông thường, cấu trúc hoặc công đoàn), có

  • ...

  • không do người dùng cung cấp , inherited, or explicit (since C++17) constructors (explicitly defaulted or deleted constructors are allowed) (since C++11)

  • ...

Điều đó có nghĩa từ C++ 11, lớp với nhà thầu bị xóa một cách rõ ràng vẫn được coi như một loại tổng hợp, sau đó tổng hợp khởi tạo được cho phép.

Và hiệu quả là:

Mỗi direct public base, (since C++17) mảng phần tử, hoặc thành viên lớp không tĩnh, theo thứ tự mảng subscript/xuất hiện trong định nghĩa lớp, là bản sao-khởi tạo từ các khoản tương ứng của initializer danh sách.

Lưu ý rằng đối DefaultPrivate y{10};, trong quá trình trên các constructor mặc định sẽ không được xem xét ở tất cả, sau đó thực tế là nó khai báo là deleteprivate sẽ không thành vấn đề.

BTW: Đối với DefaultPrivate x;default initialization được thực hiện,

nếu T là một loại non-POD (until C++11) lớp, các nhà thầu được xem xét và chịu sự quá tải độ phân giải so với danh sách đối số rỗng.Hàm khởi tạo được chọn (là một trong các hàm tạo mặc định) được gọi để cung cấp giá trị ban đầu cho đối tượng mới;

do đó hàm tạo mặc định được cố gắng sử dụng nhưng đó là delete sau đó biên dịch không thành công.

Nếu bạn sử dụng tổng hợp khởi tạo, như DefaultPrivate x{};, mã cũng sẽ hoạt động tốt; và n_ sẽ là value initialized (và sau đó zero initialized) là 0.

LIVE

+0

Có, loại này được tổng hợp, nhưng tổng hợp theo nghĩa riêng tư hoặc tôi hy vọng nó sẽ là, nếu không tôi sẽ không sử dụng tổng hợp trong title –

+1

@WernerErasmus Trả lời sửa đổi. Vấn đề là các nhà xây dựng sẽ không được xem xét cho trường hợp này, vì vậy nó không quan trọng. – songyuanyao

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