如果你有一个const
参考B
类型的一些实例存储到你的A
类,那么你一定要得到保证,A
实例的那一世将B
实例的生命周期超过:
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!
为了使它成为可能,您应该明确地指定= delete;
所有的构造函数重载,它们可以接受右值(包括const &&
和&&
)。为了达到这个目的,你只需要= delete;
只有const &&
版本的构造函数。
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 &&`
};
此方法允许您禁止传递给构造函数所有类型的右值。
这也适用于内置标量。例如,double const f() { return 0.01; }
,虽然它造成类似的警告:
警告:在返回类型“常量”类型限定符没有效果[-Wignored-预选赛]
还算可以,如果你有效果只是= delete;
只有&&
版本的构造函数:
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!
对于非转换构造函数(即非一元),有一个问题:你可能需要提供= delete;
-d版本所有构造的combinatorically可能版本如下:
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;
};
,禁止混合情况下,像:
B b{};
A a{b, C{}};
临时不结合左值参考。在第一个例子中定义'r2'不应该编译。 – musiphil
如果您使用的是VC++,一种解决方案是打开警告级别,它会告诉您什么时候它不起作用。 –
但是,_const_引用会绑定到一个临时的,所以这个问题仍然是一个很好的问题。我已经考虑过这种方法,但我仍然认为,如果一个类将存储引用对象的引用(或指针),最好在构造函数中使用指针,以使潜在的生命期关注点有点更明显(当一个构造函数接受一个指针时,通常它会让我三次思考对象将如何处理它)。 –