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

How to force std::vector to use move constructor instead of the copy one?

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

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 编译器失败并出现错误:

error: use of deleted function ‘TestData::TestData(const TestData&)’

但我不想复制数据,我想移动它。原因是复制数据会导致复制指针 (ptr),因此尝试在析构函数中删除它会导致双重损坏。

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

这次通话

vector.push_back(d);

不会调用您的移动构造函数,因为 d 不是右值引用。如果为非 r 值引用调用移动构造函数会很糟糕,因为它会撕掉本应保持完整的对象的内脏。您需要转换为 r 值引用,以明确表示您不再需要 d。这就是 std::move 所做的(实际上只是演员):

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

但是,TestData 的默认移动构造函数没有做正确的事情。在上面的行 ptr 仍然由移动的对象拥有之后,导致双重删除。您可以通过使用 std::string 作为成员而不是 char *.

来防止出现这种情况以及您的字符串未被空终止的问题