使用派生的右值引用初始化基

Initializing base with rvalue reference of derived

在下面的代码中:

struct A {
    A() {}
    A(A &&) { printf("moving A\n"); }
    ~A() { printf("destructing A\n"); }
};

struct B : A {
    B() {}
    B(B &&) { printf("moving B\n"); }
    ~B() { printf("destructing B\n"); }
};

B func() {
    B b;
    return b;
}

int main() {
    A a = func();
    printf("hello\n");
}

生成以下输出:

moving A
destructing B
destructing A
hello
destructing A

为什么没有省略这一步棋?为什么调用 A 的移动构造函数而不调用 B 的移动构造函数?这里到底发生了什么?

Why is the move constructor of A called but not that of B?

因为您正在构造一个 A,所以只会考虑 A 的构造函数。特别是,func()返回的临时B可以绑定到A&&,然后使用A的移动构造函数构造a;换句话说,a 是从临时 B.

中切出的

Why isn't the move elided?

Copy elision 在这种情况下是不允许的,a 必须从临时 B.

构造

First, if T is a class type and the initializer is a prvalue expression whose cv-unqualified type is the same class as T, the initializer expression itself, rather than a temporary materialized from it, is used to initialize the destination object: see copy elision

func() returns 一个 B,与 A 完全不是同一类型。