官术网_书友最值得收藏!

Rvalue references

We cannot bind lvalue references to temporaries. The following code won't compile:

int get_it() {
int it{42};
return it;
}
...
int& impossible{get_it()}; // compile error

We need to declare an rvalue reference to be able to bind to temporaries (including literal values):

int&& possible{get_it()};

Rvalue references allow us to skip the generation of temporaries as much as possible. For example, a function that takes the result as an rvalue reference runs faster by eliminating temporary objects:

void do_something(int&& val) {
// do something with the val
}
// the return value of the get_it is moved to do_something rather than copied
do_something(get_it());

To imagine the effect of moving, imagine that the preceding code will be translated into the following (just to get the full idea of moving):

int val;
void get_it() {
val = 42;
}
void do_something() {
// do something with the val
}
do_something();

Before moving was introduced, the preceding code would look like this (with some compiler optimization):

int tmp;
void get_it() {
tmp = 42;
}
void do_something(int val) {
// do something with the val
}
do_something(tmp);

The move constructor, along with the move operator, =(), has the effect of copying without actually carrying out a copy operation when the input argument represents an rvalue. That's why we should also implement these new functions in the class: so that we can optimize the code wherever it makes sense. The move constructor can grab the source object instead of copying it, as shown here:

class Warehouse {
public:
// constructors omitted for brevity
Warehouse(Warehouse&& src)
: size_{src.size_},
capacity_{src.capacity_},
products_{src.products_}
{
src.size_ = 0;
src.capacity_ = 0;
src.products_ = nullptr;
}
};

Instead of creating a new array of capacity_ size and then copying each element of the products_ array, we just grabbed the pointer to the array. We know that the src object is an rvalue and that it will soon be destroyed, which means the destructor will be called and the destructor will delete the allocated array. Now, we point to the allocated array from the newly created Warehouse object, which is why we cannot let the destructor delete the source array. Due to this, we assign nullptr to it to make sure the destructor will miss the allocated object. So, the following code will be optimized because of the move constructor:

Warehouse large = small + mid;

The result of + operator will be moved rather than copied. Take a look at the following diagram:

The preceding diagram demonstrates how the temporary is being moved to the large object.

主站蜘蛛池模板: 阳朔县| 田东县| 丰台区| 寿宁县| 涞水县| 嘉义县| 福泉市| 赤峰市| 莫力| 南安市| 无极县| 陆良县| 南阳市| 抚松县| 巧家县| 当涂县| 定西市| 肇庆市| 苏尼特左旗| 合阳县| 夏津县| 东港市| 临汾市| 东光县| 睢宁县| 抚顺市| 北辰区| 建昌县| 平阳县| 牙克石市| 穆棱市| 宣城市| 抚松县| 德令哈市| 平邑县| 诸暨市| 临潭县| 绍兴县| 永德县| 静安区| 宽城|