如何强制std::vector使用移动构造函数而不是复制构造函数?

问题描述 投票:0回答:1

我想在我的应用程序中使用移动语义,而不是复制数据。

using namespace std;

struct TestData
{
    TestData(const TestData&) = delete;
    TestData& operator=(const TestData&) = delete;
    TestData(TestData &&other) = default;
    TestData& operator=(TestData &&other) = default;

    TestData() { std::cout << "TestData()" << std::endl; }
    ~TestData() noexcept {
        if(ptr != null) delete []ptr;
        std::cout << "~TestData(), ptr = " << (ptr == nullptr ? "nullptr" : "not null") << std::endl; 
    }
    int x;
    char *ptr = nullptr;
};

void add(std::vector<TestData> &vector)
{
    TestData d;
    d.x = 1;
    d.ptr = new char[12];
    memcpy(d.ptr, "Test string", 11);
    vector.push_back(d);
}


int main()
{
    std::vector<TestData> v;
    add(v);
    add(v);

    return 0;
}

但是GCC编译器出错了:

错误:使用被删除的函数'TestData::TestData(const TestData&)'。

但是我不想复制数据,我想移动数据。原因是复制数据会导致复制指针(ptr),所以试图在destructor中删除它会导致双自由损坏。

所以问题是--如何强制GCC使用移动构造函数?

  • GCC v. 9.3.0
  • Ubuntu 20.04
c++ c++11 gcc move-semantics
1个回答
3
投票

这个调用

vector.push_back(d);

不调用你的移动构造函数,因为 d 不是一个r值引用。如果对非 r-value 引用调用 move 构造函数,那就不好了,因为它会把本应保持完整的对象的内脏撕掉。你需要投射到 r-value 引用,以明确你不再需要 d. 这就是 std::move (它实际上只是一个投射)。

vector.push_back(std::move(d));

然而,默认的move构造函数 TestData 是做的不对。在上面一行字之后 ptr 仍然是被移出的对象所拥有,从而导致双重删除。您可以通过使用 std::string 作为成员,而非 char *.

© www.soinside.com 2019 - 2024. All rights reserved.