简体   繁体   English

带有右值引用的C ++构造函数

[英]C++ constructor with rvalue reference

Consider this class with three constructors: 考虑这个有三个构造函数的类:

class Circle {

public:
 Circle(int r) {
      _radius = r;
 }

Circle(const Circle& c){
    _radius = c.radius();
    cout << endl << "Copy constructor with lvalue reference. Radius: " << _radius;
}

Circle(Circle&& c){
    _radius = c.radius();
    cout << endl << "Copy constructor with rvalue reference. Radius:" << _radius;
}

int radius() const {
    return _radius;
}

private:
    int _radius;
};

int main() {
     Circle c1(2);
     Circle c2(c1);
     cout << endl << c2.radius(); 
     Circle c3(Circle(4));
     cout << endl << c3.radius(); 
     return 0;
 }

Compiled with "g++ -std=c++0x". 用“g ++ -std = c ++ 0x”编译。 The output is: 输出是:

Copy constructor with lvalue reference. Radius: 2
2
4

OK. 好。 The right constructors for the first two cases are called. 调用前两种情况的正确构造函数。 But for the third case ie, Circle c3(Circle(4)), I'd expect the third constructor, (copy constructor with rvalue referecne) to be called but it's not the case. 但是对于第三种情况,即Circle c3(Circle(4)),我期望第三个构造函数(带有rvalue referecne的复制构造函数)被调用,但事实并非如此。 Obviously some constructor is called since c3 is properly instantiated but I don't understand why the compiler is not using the explicitly provided one. 显然有一些构造函数被调用,因为c3被正确实例化了,但我不明白为什么编译器没有使用明确提供的编译器。 Am I missing something here? 我在这里错过了什么吗?

No move constructors are being called because your compiler is too smart for your code ;) 没有调用move构造函数,因为你的编译器对你的代码太聪明了;)

 Circle c1(2);

This just constructs an object with the int conversion constructor. 这只是用int转换构造函数构造一个对象。

 Circle c2(c1);

This is a copy operation. 这是一个复制操作。 c1 is an l-value, so it provokes a copy. c1是一个l值,因此它会引发一个副本。

 Circle c3(Circle(4));

Here, your compiler recognizes that you're basically telling it to construct the object twice. 在这里,您的编译器会认识到您基本上是在告诉它构造对象两次。 So it elides one of the object constructors. 所以它省略了一个对象构造函数。 This is allowed in this instance by the C++ specification. 在这种情况下,C ++规范允许这样做。

If your compiler couldn't elide the construction, then it would perform an move. 如果您的编译器无法忽略构造,那么它将执行移动。 Also, if your compiler can't elide that , throw it away. 此外,如果您的编译器无法忽略 ,请将其丢弃。

So there's no moving going on. 所以没有动人的事。

In order to take the rvalue reference, it should be non-const, since the contents of the constructor argument will be moved and typically this is an operation that changes the state of the operand (although not in your particular case): 为了获取rvalue引用,它应该是非const的,因为构造函数参数的内容将被移动,并且通常这是一个更改操作数状态的操作(尽管不是在您的特定情况下):

Circle(Circle&& c){ }

Also, you are seeing a copy elision here: 此外,您在这里看到了一个副本省略:

Circle c3(Circle(4));

so the move constructor doesn't get invoked. 所以不会调用move构造函数。 This is a standard compiler optimization that may or may not happen. 这是可能会或可能不会发生的标准编译器优化。 If you were to construct a Circle like this: 如果你要像这样构建一个Circle

Circle c3(std::move(c1));

then you would invoke the move constructor. 然后你会调用移动构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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