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

  • Expert C++
  • Vardan Grigoryan Shunguang Wu
  • 433字
  • 2021-06-24 16:34:02

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.

主站蜘蛛池模板: 江口县| 独山县| 礼泉县| 沧源| 元谋县| 黄冈市| 宁城县| 小金县| 木兰县| 邹城市| 马边| 昭平县| 密山市| 平和县| 永登县| 阳西县| 宁阳县| 德格县| 青龙| 灵璧县| 西华县| 神农架林区| 闽清县| 浦江县| 东港市| 普陀区| 根河市| 土默特右旗| 阜阳市| 永定县| 东莞市| 含山县| 新巴尔虎右旗| 江津市| 孝感市| 乌兰浩特市| 涞水县| 邢台市| 桑日县| 岑溪市| 仙游县|