避免使用vector :: push_back复制

时间:2019-06-15 12:02:48

标签: c++ c++11 stl

我创建了一个名为“ Resource”的类,并手工制作了构造函数,包括复制构造函数和move构造函数以及复制赋值和移动赋值运算符。

如我所料,插入右值时,仅调用move构造函数。当我插入一个左值时,进行了两个复制构造函数调用。

但是当我使用std :: move将左值转换为右值并使用push_back时,我感到很惊讶,我观察到一个移动构造函数的调用,随后是两次复制构造函数的调用。

经过一番思考,我猜想该复制是由向量在内部完成的。因此,我通过设置任何插入之前的容量来测试我的理论,并且观察到我发现std :: move和push_back没有复制。

class Resource
{
public:
Resource(std::string s) : str(std::move(s)) {}
~Resource() = default;
Resource(const Resource &r) {
    std::cout << "Copy constructor" << std::endl;
    str = r.str;
}
Resource& operator=(const Resource &r) {
    std::cout << "Copy assignment" << std::endl;
    if (this != &r)
    {
        str = r.str;
    }
    return *this;
}
Resource(Resource &&r) {
    std::cout << "Move constructor" << std::endl;
    str = std::move(r.str);
    r.str.clear();
}
Resource& operator=(Resource &&r) {
    std::cout << "Move assignment" << std::endl;
    str = std::move(r.str);
    r.str.clear();
    return *this;
}

private:
std::string str;
};


int main()
{
    std::vector<Resource> vec;
    //vec.reserve(3);
    vec.push_back(Resource("hello"));
    Resource r("world");
    vec.push_back(r);
    vec.push_back(std::move(r));
    return 0;
}

在main的第二行注释掉后得到:
移动构造函数
复制构造函数
复制构造函数
移动构造函数
复制构造函数
复制构造函数

当该行取消注释时,即我调用vec.reserve(3),我得到:
移动构造函数
复制构造函数
移动构造函数

这表明即使您定义了move构造函数,如果您没有保留足够的空间,也会继续进行复制。

有什么办法可以避免这种情况?

更新:我更正了=运算符以返回引用。我不知道您必须向编译器提供noexcept提示,以防止这种情况的发生。

0 个答案:

没有答案