2017-06-23 7 views
4

私のプロジェクトでは、オブジェクトの大半はアリーナで作成され、ユーザーセッション中に存在することが保証されています。 いくつかのクラスはメンバーフィールドとしてconst参照を持っているので、それは例えば、非常に安全です:参照での値渡しの防止

class A { 
public: 
    A(const string& str) : str_(str) {} 

private: 
    const string& str_; 
}; 

しかし、ここで落とし穴があります。時間的stringオブジェクトが暗黙的に作成され、破壊されたその線で

A a("some temporal string object"); 

:誤ってA次の方法でインスタンスを作成することが可能です。そのため、その後aは誤った参照を格納します。

この動作を防止するにはどうすればよいですか?コンパイルエラーが発生した方が良いでしょう...

+1

あなたのアリーナはちょうどそれはすべきではないメモリの大きなブロックを配布する場合'this'がそれに属しているかどうかをチェックし、コンストラクタに関連する' assert'を追加するのは難しいです。代わりに、コンストラクタをプライベートにして、アリーナを使用してオブジェクトを割り当てるファクトリメソッドを提供することもできます。これには、コンパイル時に間違いが検出されるという利点もあります。 –

+0

待ってはいけません。あなたが任意のタイプで動作するようになりましたので、2番目の方法は実現できません。 –

+0

@MatteoItalia、ねえ、タイプはアリーナについて何も知らないはずです)そして、私はアリーナについて書いたのは、メンバーフィールドとしての参照を正当化することだけです。 – Alexey

答えて

3

コンパイラがconst&よりも1つ大きい値になるように、より大きな値に一致するオーバーロードが必要です。

ので、一時的に良くマッチconst&より&&ので、あなたは、まさにこのようなコンストラクタを提供する必要があるとdeleteそれ:

class A { 
public: 
    A(const string& str) : str_(str) {} 
    A(string&&) = delete; // this constructor is a better match for rvalues 

private: 
    const string& str_; 
}; 
+0

これはスタック割り当てオブジェクトでは役に立ちません。 –

+0

@MatteoItaliaそうだけど、唯一実行可能な解決策は、すべてのIMOを参照しないことです。 – Rakete1111

+2

ええ、おそらく正しい解決策は、ポインターをラップするスマートポインターのようなオブジェクトを取ることだけで、アリーナによってのみ生成することができます。 –

関連する問題