Nếu bạn có để lưu trữ một tham chiếu const
đối với một số thể hiện của loại B
vào lớp học của bạn A
, thì chắc chắn bạn muốn được đảm bảo, rằng tuổi thọ của A
dụ sẽ được vượt quá bởi tuổi thọ của B
dụ:
B b{};
A a1{b}; // allowed
A a2{B{}}; // should be denied
B const f() { return B{}; } // const result type may make sense for user-defined types
A a3{f()}; // should also be denied!
Để làm cho nó có thể bạn nên rõ ràng để = delete;
tất cả các quá tải constructor, có thể chấp nhận rvalues (cả hai const &&
và &&
). Để đạt được điều này, bạn chỉ nên = delete;
chỉ const &&
phiên bản của hàm tạo.
struct B {};
struct A
{
B const & b;
A(B const & bb) : b(bb) { ; } // accepts only `B const &` and `B &`
A(B const &&) = delete; // prohibits both `B &&` and `B const &&`
};
Cách tiếp cận này cho phép bạn cấm chuyển cho nhà xây dựng tất cả các loại giá trị.
Điều này cũng hoạt động đối với các vô hướng tích hợp.Ví dụ, double const f() { return 0.01; }
, mặc dù nó gây ra một cảnh báo như:
cảnh báo: 'const' loại vòng trên kiểu trả về không có tác dụng [-Wignored-vòng loại]
nó vẫn có thể có tác dụng nếu bạn chỉ = delete;
chỉ &&
phiên bản của constructor:
struct A
{
double const & eps;
A(double const & e) : eps(e) {} // binds to `double const &`, `double &` AND ! `double const &&`
A(double &&) = delete; // prohibit to binding only to `double &&`, but not to `double const &&`
};
double const get_eps() { return 0.01; }
A a{0.01}; // hard error
A a{get_eps()}; // no hard error, but it is wrong!
đối với nhà xây dựng không chuyển đổi (tức là không unary) có một vấn đề: bạn có thể phải cung cấp = delete;
phiên bản -d cho tất cả các phiên bản combinatorically có thể có của nhà xây dựng như sau:
struct A
{
A(B const &, C const &) {}
A(B const &&, C const &&) = delete;
// and also!
A(B const &, C const &&) = delete;
A(B const &&, C const &) = delete;
};
cấm hỗn hợp các trường hợp như:
B b{};
A a{b, C{}};
Tồn tại tạm thời không liên kết với một tài liệu tham khảo giá trị trái. Định nghĩa của 'r2' trong ví dụ đầu tiên của bạn không nên biên dịch. – musiphil
Nếu bạn đang sử dụng VC++, một giải pháp là để bật lên mức cảnh báo và nó sẽ cho bạn biết khi nào nó không hoạt động. –
Tuy nhiên, một tham chiếu _const_ sẽ liên kết với một tạm thời, vì vậy câu hỏi vẫn là một câu hỏi hay. Tôi đã xem xét cách tiếp cận này, nhưng tôi vẫn cho rằng nếu một lớp sẽ lưu trữ một tham chiếu (hoặc con trỏ) đến đối tượng được tham chiếu, thì tốt hơn là lấy một con trỏ trong hàm tạo, bit rõ ràng hơn (khi một nhà xây dựng có một con trỏ, thường nó làm cho tôi suy nghĩ hai lần về những gì đối tượng sẽ làm gì với nó). –