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

C++ 使用派生的右值引用初始化基,c++,class,inheritance,constructor,move-semantics,C++,Class,Inheritance,Constructor,Move Semantics,在以下代码中: 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() {

在以下代码中:

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的移动构造函数?这里到底发生了什么

为什么调用了A的移动构造函数而没有调用B的移动构造函数

因为您正在构造一个
A
,所以只会考虑
A
的构造函数。特别地,由
func()
返回的临时
B
可以绑定到
A&
,然后使用
A
的移动构造函数来构造
A
;在另一个单词中,
a
从临时
B
中切片

为什么这一举措没有被省略

在这种情况下是不允许的,
a
必须从临时
B
构造

首先,如果
T
是一个类类型,并且初始值设定项是一个prvalue表达式,其cv非限定类型与
T
是同一个类,则初始值设定项表达式本身,而不是它的临时物化,用于初始化目标对象:请参阅


func()
返回一个
B
,该类型与
a
的类型不同。

当临时
B
被销毁时,为什么对
B
的析构函数调用发生在
a
之前?@0x499602D2,首先调用
B
的析构函数,然后调用它的基类,即
A
的析构函数。如果一个对象被移动,为什么会被析构函数两次?@wispi第一次发生在临时
B
被销毁时,其中包括
B
的析构函数和
A
的析构函数的发票。即使临时
B
被移动,它仍然需要被描述。第二种情况发生在
a
被销毁时。