参照を初期化するときは、値ごとにコピーを避けてください
-
25-10-2019 - |
質問
関数インターフェイスがあります:
struct iFace {
virtual Type& getType() = 0;
}
そして、アイデアはそれを取得することです:
iFace& iface = getIface();
Type& type = iface.getType();
しかし、私は時折、私は間違いをして書いています:
Type type = iface.getType();
これは価値ごとにコピーします。これは私が避けたいものです。ただし、そのような間違いを犯した場合、コンパイラは法的構文のために警告を発しません。このためにコンパイル時間エラーをトリガーしたいのですが、 質問 私の選択肢は何ですか?
私はコピーコンストラクターを宣言することを考えましたが、どこにも定義しないため、使用されている場合はリンク時間エラーが発生しますが、コピーコンストラクターを使用することはできません。 どれか 状況、それは必須ではありません
解決
コピーコンストラクターと割り当てオペレーターを「プライベート」に置くことにより、Ifaceを非コピーにします。次に、明示的なコピー方法を提供します。
class Type {
public:
virtual Copy(Type& dest) = 0;
private:
Type (const Type &) {assert(false)}
Type & operator=(const Type &) {assert(false)}
}
使用することもできます コピーできないブースト 同じことをするために(上記のように実装)。
だからあなたのコードをコピーしたいなら、あなたはそうするでしょう
Type& type = iface.getType();
Type typeCpy;
type.Copy(typeCpy);
余談です - パフォーマンスの懸念のためにこれを行っている場合、オプティマイザーがあなたのための一時的なコピーを取り除いていないと確信していますか?
他のヒント
ここではポインターを返すと合理的に思えますが、所有権を混乱させると心配すると、参照の周りにラッパーを返すことができます。
struct Class {
struct Ref {
Ref(Class& c_) : c(c_) { }
Class Clone() { return c; }
// overload -> to provide access to c
private:
Class& c;
};
};
元のクラスは通常どおりコピーできますが、参照は明示的に行う必要があります。私はこのアイデアに熱心ではありません(セマンティクスのコピーがどのように機能しているかを理解していないユーザーは、これらの1つが長すぎると誤って保持している人よりも少ないと思います)が、理論的には実行可能です。
所属していません StackOverflow