我是SO的新手,所以让我知道是否需要更改任何内容。我竭尽全力提供示例代码。我知道已经问过许多类似的问题,但是我找不到与我的特定问题匹配的问题。
此外,我知道我在做的事情不是用“真实”代码做的事情,我只是想更好地理解r / l / p / x..values。 / p>
我有一个基类和一个派生类,它们都有默认,复制和移动构造函数。现在,我想让派生类的副本构造函数调用基类的move构造函数。
class Base
{
public:
Base(){ std::cout << "default base constructor called.\n"; }
Base(Base const &other) { std::cout << "copy base constructor called.\n"; }
Base(Base &&tmp) { std::cout << "move base constructor called.\n"; }
};
与派生类基本相同:
class Derived : public Base
{
public:
Derived(){ std::cout << "default derived constructor called.\n";}
Derived(Derived const &other)
:
Base(std::move(other)) // here I want to call Base(Base &&tmp)
{
std::cout << "copy derived constructor called.\n";
}
Derived(Derived &&tmp)
:
Base(std::move(tmp)) // correctly calls Base(Base &&tmp)!
{
std::cout << "move derived constructor called.\n";
}
};
所以在我的主函数中,我现在要调用复制构造函数,然后再调用基类的move构造函数。
int main()
{
Derived der{};
Derived der_copy{ der };
Derived der_move{ std::move(der) };
}
我得到的输出是这样:
default base constructor called.
default derived constructor called.
copy base constructor called. <-- why not move?
copy derived constructor called.
move base constructor called.
move derived constructor called.
我期望以下几点:
default base constructor called.
default derived constructor called.
move base constructor called.
copy derived constructor called.
move base constructor called.
move derived constructor called.
因此,当我在派生的移动构造函数中使用std::move(tmp)
时(在Base &&tmp
上),将调用基本move构造函数,但是当我在派生的复制构造函数中使用std::move(other)
时(因此在Base const &other
上调用了基本副本构造函数?
TBH,这似乎太奇怪了,以至于我怕自己在代码中犯了一个错误,我多次检查了所有内容,但似乎无法在上述情况下调用move base构造函数... < / p>
感谢您的帮助!
答案 0 :(得分:2)
在复制构造函数中
Derived(const Derived& other)
std::move(other)
将导致类型为const Derived&&
的xvalue表达式。
这是一个合法但有些奇怪的类型:std::move(other)
是一个临时对象,但是您不能从它移开,因为它是常量。此类引用具有limited number of use cases。有关一个特定示例,请参见std::as_const
和std::ref
的声明。
const Derived&&
无法绑定到Base&&
,这就是为什么在之间的重载解析期间
Base(const Base&)
Base(Base&&)
前者由编译器选择。
冒着获得不确定行为的风险,您可以放弃constness并编写
Derived(const Derived& other) : Base(std::move(const_cast<Derived&>(other))) {}
调用Base
的move构造函数。但是不要在真实代码中这样做。
答案 1 :(得分:1)
您需要像这样更改您的基类:
Base(const Base &&tmp) { std::cout << "move base constructor called.\n"; }