哪个构造函数将触发移动语义?

Which constructor will trigger the move semantics?

我目前正在学习 C++,并且想知道哪一个是正确的使用方法std::move

//Code might be incorrect since I havent tested it out
Xyt::ByteArray* Xyt::ResourceManager::LoadFileToByteArray(std::string Path)
{
try {
    std::ifstream FileStream(Path, std::ios::in);
    std::ifstream::pos_type Pos = FileStream.tellg();

    FileStream.seekg(0, std::ios::beg);

    std::vector<char> Buff(Pos);
    FileStream.read(Buff.data(), Pos);

    FileStream.close();

    //I want to trigger the move constructor here
    return new Xyt::ByteArray(std::move(Buff));
}
catch (std::exception e) {
    std::cout << "ERROR::FILE::FILE_NOT_SUCCESFULLY_READ" << Path << std::endl;
    return nullptr;
    }
}

我感到困惑的是哪个会触发 std::vector 的移动构造函数?

是这个吗(调用者不使用std::move时编译错误)

Xyt::ByteArray::ByteArray(std::vector<char>&& Buffer)
{
    this->Buffer = Buffer;
}

这个(同时接受 std::move(Buff) 和 Buff)?

Xyt::ByteArray::ByteArray(std::vector<char> Buffer)
{
    this->Buffer = Buffer;
}

还是这个?

Xyt::ByteArray::ByteArray(std::vector<char> Buffer)
{
    this->Buffer = std::move(Buffer);
}

根据我在网上阅读的理解,第一个构造函数是利用移动语义的正确方法。但是,如果我使用第一个构造函数是否意味着如果我想在 std::vector Buff 上实际做一个副本,我需要创建另一个构造函数?

如有任何帮助,我们将不胜感激!

唯一有效的是第三个。但那是因为您在 构造函数中使用了 std::move 。并且引发了两招:一是填入参数,一是从参数入值。

正确的做法是:

Xyt::ByteArray::ByteArray(std::vector<char>&& Buf)
  : Buffer(std::move(Buf))
{}

这只会调用一次移动操作。

如果要调用移动操作,则必须显式地从命名右值引用中移动。


But if I use the 1st constructor does that mean I need to make another constructor if I want to actually do a copy on the std::vector Buff ?

您不一定非得这样做。您可以要求用户在调用函数时自己进行复制:

Xyt::ByteArray(std::vector<char>(Buff))

但是是的,如果你希望用户直接提供一个左值,并且你想从左值复制,那么你需要提供一个构造函数,它接受一个 (const) 左值引用并执行复制.