如果你有一個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_引用會綁定到一個臨時的,所以這個問題仍然是一個很好的問題。我已經考慮過這種方法,但我仍然認爲,如果一個類將存儲引用對象的引用(或指針),最好在構造函數中使用指針,以使潛在的生命期關注點有點更明顯(當一個構造函數接受一個指針時,通常它會讓我三次思考對象將如何處理它)。 –