C++11 では、次のコードを記述できます。
struct Cat {
Cat(){}
};
const Cat cat;
std::move(cat); //this is valid in C++11
を呼び出すとstd::move
、オブジェクトを移動したい、つまりオブジェクトを変更することを意味します。オブジェクトを移動するのはconst
不合理なので、なぜstd::move
この動作を制限しないのでしょうか? 将来的には罠になるでしょう?
ここでのトラップとは、Brandon がコメントで述べたとおりの意味です。
「彼は、それが彼を卑劣に「罠にかける」という意味だと私は思います。なぜなら、彼が気付かなければ、結局は彼が意図していなかったコピーを手にしてしまうことになるからです。」
Scott Meyers 氏の著書『Effective Modern C++』では、次のような例が挙げられています。
class Annotation {
public:
explicit Annotation(const std::string text)
: value(std::move(text)) //here we want to call string(string&&),
//but because text is const,
//the return type of std::move(text) is const std::string&&
//so we actually called string(const string&)
//it is a bug which is very hard to find out
private:
std::string value;
};
std::move
オブジェクトに対する操作が禁止されていればconst
、バグは簡単に見つかるのではないでしょうか?
ベストアンサー1
ここであなたが見落としているトリックがあります。std::move(cat)
実際には何も動かないコンパイラに指示するだけです試す移動します。ただし、クラスには を受け入れるコンストラクターがないためconst CAT&&
、代わりに暗黙のconst CAT&
コピー コンストラクターを使用して安全にコピーします。危険もトラップもありません。何らかの理由でコピー コンストラクターが無効になっている場合は、コンパイラ エラーが発生します。
struct CAT
{
CAT(){}
CAT(const CAT&) {std::cout << "COPY";}
CAT(CAT&&) {std::cout << "MOVE";}
};
int main() {
const CAT cat;
CAT cat2 = std::move(cat);
}
印刷されますCOPY
が、 ではありませんMOVE
。
http://coliru.stacked-crooked.com/a/0dff72133dbf9d1f
あなたが言及したコードのバグはパフォーマンス問題ではなく、安定性問題は、このようなバグがクラッシュを引き起こすことはないということです。単に遅いコピーを使用するだけです。さらに、このようなバグは、移動コンストラクタを持たない非constオブジェクトでも発生するため、オーバーconst
ロードを追加するだけでは、すべてをキャッチすることはできません。パラメータ型から移動コンストラクトまたは移動割り当てが可能かどうかをチェックすることもできますが、そうすると、汎用テンプレートコードが妨げられてしまいます。想定コピー コンストラクターに頼ることになります。それに、 から構築したい人もいるかもしれませんがconst CAT&&
、できないと私が言う資格があるでしょうか?