C++11 rvalue reference calling copy constructor too

旧巷老猫 提交于 2019-11-28 21:13:31

Put noexcept on your move constructor:

TestClass(TestClass&& other) noexcept {

Elaboration: I was going to give this one Pierre, but unfortunately the cppreference source is only approximately correct.

In C++03

vector<T>::push_back(T)

has the "strong exception guarantee". That means that if the push_back throws an exception, the vector is left in the same state it had prior to the call to push_back.

This guarantee is problematic if the move constructor throws an exception.

When the vector reallocates, it would like to move the elements from the old buffer to the new. However if any one of those moves throws an exception (besides the first), then it is left in a state where the old buffer has been modified, and the new buffer doesn't yet contain everything it is supposed to. The vector can't restore the old buffer to its original state because it would have to move elements back to do so, those moves might also fail.

So a rule was laid down for C++11:

  1. If T has a noexcept move constructor, that can be used to move the elements from the old buffer to the new.

  2. Otherwise if T has a copy constructor, that will be used instead.

  3. Otherwise (if there is no accessible copy constructor), then the move constructor will be used after all, however in this case, the strong exception safety guarantee is no longer given.

Clarification: "copy constructor" in rule 2 means a constructor taking a const T&, not one of those weenie so-called T& copy constructors. :-)

Use noexcept on your move constructor :

TestClass(TestClass&& other) noexcept { ... }

noexcept without a constant expression like this is equivalent to noexcept(true).

The compiler can use this information to enable certain optimizations on non-throwing functions as well as enable the noexcept operator, which can check at compile time if a particular expression is declared to throw any exceptions.

For example, containers such as std::vector will move their elements if the elements' move constructor is noexcept, and copy otherwise.

Source : http://en.cppreference.com/w/cpp/language/noexcept_spec

NB : This is a C++11 feature. Certain compiler may not have implemented it yet... (ex: Visual Studio 2012)

maestroIgor

Copy constructor is called when all reserved memory inside std::vector is used. It is necessary to call std::vector::reserve() method before adding the elements.

vector<TestClass> vec;
vec.reserve(500000);

Another question. In the move constructor,

// move constructor
TestClass(TestClass&& other){
    arr=other.arr;
    size=other.size;

    other.arr=nullptr;
    other.size=0;
}

Shouldn't it be

arr=std:move(other.arr);

size=std:move(other.size);

because

the fact that all named values (such as function parameters) always evaluate as lvalues (even those declared as rvalue references)

?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!