我最近在学习移动构造函数,我遇到了一个奇怪的问题。 我有以下代码:
sap.m.table
输出结果为:
#include <iostream>
class a
{
public:
a() { printf("default\n"); }
a(const a& aa) { printf("const lr\n"); }
a(a& aa) { printf("lr\n"); }
a(a&& aa) { printf("rr\n"); }
a(const a&& aa) { printf("const rr\n"); }
};
a foo()
{
return a();
}
void func(a& a) {
printf("func lr\n");
}
void func(a&& aa) {
printf("func rr\n");
}
int main()
{
printf("a1: ");a a1;
printf("a2: ");a a2(a1);
printf("a3: ");a a3(std::move(a2));
printf("a4: ");a a4(foo());
printf("a5: ");a a5(std::move(foo()));
func(foo());
}
除了a4之外,一切都很好。我希望a1: default
a2: lr
a3: rr
a4: default
a5: default
rr
default
func rr
的返回类型是一个右值。我认为foo()
的呼吁最终证明了这一点。那么为什么在构造a4时没有调用移动构造函数呢?同时,在构建a5时会调用它。
答案 0 :(得分:6)
这可能是因为copy_elision
。
在下列情况下,编制者需要省略 类对象的复制和移动构造:
- 在初始化中,如果初始化表达式是prvalue且源类型的cv-nonqualified版本与目标类相同,则初始化表达式用于初始化目标对象:
醇>
T x = T(T(T())); // only one call to default constructor of T, to initialize x
- 醇>
在函数调用中,如果return语句的操作数是prvalue,并且函数的返回类型与该prvalue的类型相同:
T f() { return T{}; } T x = f(); // only one call to default constructor of T, to initialize x T* p = new T(f()); // only one call to default constructor of T, to initialize *p
你的情况属于第二种情况。