1. ホーム
  2. c++

[解決済み] なぜ `std::move` を `const` オブジェクトに使うことができるのですか?

2022-05-10 07:54:19

疑問点

C++11では、このようなコードを書くことができます。

struct Cat {
   Cat(){}
};

const Cat cat;
std::move(cat); //this is valid in C++11

を呼び出すと std::move を呼び出した場合、それはオブジェクトを移動させたい、つまりオブジェクトを変更することを意味します。を移動させるには const オブジェクトを動かすことは理不尽なことですが、ではなぜ std::move はこの振る舞いを制限しないのでしょうか? 将来的に罠にはまりそうですよね?

ここでいうトラップとは、ブランドンがコメントで述べているような意味です。

もし彼が気づかなかったら、彼は自分の意図しないコピーを手に入れてしまうからです。 なぜなら、もし彼が気づかなければ、彼は意図しないコピーで終わってしまうからです。

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 オブジェクトの操作が禁止されていれば、簡単にバグを発見することができますよね?

どのように解決するのですか?

struct strange {
  mutable size_t count = 0;
  strange( strange const&& o ):count(o.count) { o.count = 0; }
};

const strange s;
strange s2 = std::move(s);

ここでは std::move の上に T const . を返します。 T const&& . に対する移動コンストラクタがあります。 strange に対して、まさにこの型を取る移動コンストラクタがあります。

と呼ばれるものです。

さて、この奇妙な型は、あなたの提案が修正するバグよりも稀であることは事実です。

しかし、その一方で、既存の std::move は一般的なコードではより効果的で、作業している型が T なのか T const .