简体   繁体   中英

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

I want to use move semantics in my application, not to copy the data. Here is the code:

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;
}

But the GCC compiler fails with the error:

error: use of deleted function 'TestData::TestData(const TestData&)'

But I don't want to copy the data, I want to move that. The reason is that copying data cause to copy the pointer (ptr) and so attempt to delete it in the destructor cause to double free corruption.

So the question - how to force that GCC will use move constructor?

  • GCC v. 9.3.0
  • Ubuntu 20.04

This call

vector.push_back(d);

does not call your move constructor, because d is not a r-value reference. It would be bad if move constructors would be called for non-r-value references, because it would rip of the guts out of objects that should stay intact. You need to cast to a r-value reference, to make explicit that you no longer need d . And thats what std::move does (it's really nothing but a cast):

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

However, the default move constructor of TestData is not doing the right thing. After the line above ptr is still owned by the moved from object resulting in a double delete. You can prevent that and the problem with your string not being null-terminated by using a std::string as member instead of the char * .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM