代码之家  ›  专栏  ›  技术社区  ›  Xyten

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

  •  2
  • Xyten  · 技术社区  · 7 年前

    我目前正在学习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的move构造函数?

    是这个吗(当调用方不使用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上进行复制,我需要生成另一个构造函数?

    任何帮助都将不胜感激!

    1 回复  |  直到 7 年前
        1
  •  2
  •   Nicol Bolas    7 年前

    唯一有效的是第三个。但那是因为你 std::move 在…内 构造函数。它引发了两个动作:一个是填充参数,另一个是从参数到值。

    正确的方法是:

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

    这只调用移动操作一次。

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


    但是如果我使用第一个构造函数,这是否意味着如果我真的想在std::vector Buff上进行复制,我需要生成另一个构造函数?

    严格来说,你不必这么做。您可以要求用户在调用函数时自己进行复制:

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

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