背后的原因:局部变量 'derived' 将被复制,尽管按名称返回
Reasoning behind: local variable 'derived' will be copied despite being returned by name
这是 Is -Wreturn-std-move clang warning correct in case of objects in the same hierarchy? 的跟进,因为我不明白某些特定情况下的推理。
struct Field {
Field();
// Field(const Field&); // (a)
int a[1000000];
};
struct Base
{
Base();
// Base(const Base&); // (b)
// Base(Base&&); // (c)
Field f;
};
struct Derived : Base { };
Base foo()
{
Derived derived;
return derived;
}
- 上面的代码编译得很好。我明白,std::move 不会做任何不同的事情。
- 取消注释 (a),您会收到警告。为什么?我相信 std::move 仍然不会做任何不同的事情。
- 取消注释 (b)(保留 (a) 未注释),再次正常工作。它与#2 有何不同?
- 取消注释 (c)(保留 (a) 和 (b) 未注释),再次显示警告。这是有道理的,std::move 可以为我们节省一份副本。
- 有 foo return 派生,再次正常工作。它与#4 有何不同?
如 link 答案和 cppreference
中所述
我们首先将 derived 视为右值,如果它不是 select XXX(/*const*/Derived&&)
(直到 C++20),那么我们将其重新视为左值。
所以只要没有Base(Derived&&)
,就复制一份
虽然我没有找到警告的全部逻辑。1. 2. 3. 应该被视为相同的 IMO(没有当前等效的警告,或者警告以备将来证明)。
对于 1.
复制和移动构造函数由编译器生成。
复制或移动最后得到相同的结果。
2.
Field
不再生成移动构造函数,使整个链复制而不是移动。
复制或移动最后得到相同的结果。
3.
Base
不再生成移动构造函数,从头开始复制。
复制或移动最后得到相同的结果。
对于 4.
Base 具有复制和移动构造函数。
复制或移动给出不同的结果。
为 5。
我们现在有匹配项 XXX(Derived&&)
(XXX
=Derieved
),因此没有完成复制。
这是 Is -Wreturn-std-move clang warning correct in case of objects in the same hierarchy? 的跟进,因为我不明白某些特定情况下的推理。
struct Field {
Field();
// Field(const Field&); // (a)
int a[1000000];
};
struct Base
{
Base();
// Base(const Base&); // (b)
// Base(Base&&); // (c)
Field f;
};
struct Derived : Base { };
Base foo()
{
Derived derived;
return derived;
}
- 上面的代码编译得很好。我明白,std::move 不会做任何不同的事情。
- 取消注释 (a),您会收到警告。为什么?我相信 std::move 仍然不会做任何不同的事情。
- 取消注释 (b)(保留 (a) 未注释),再次正常工作。它与#2 有何不同?
- 取消注释 (c)(保留 (a) 和 (b) 未注释),再次显示警告。这是有道理的,std::move 可以为我们节省一份副本。
- 有 foo return 派生,再次正常工作。它与#4 有何不同?
如 link 答案和 cppreference
中所述我们首先将 derived 视为右值,如果它不是 select XXX(/*const*/Derived&&)
(直到 C++20),那么我们将其重新视为左值。
所以只要没有Base(Derived&&)
,就复制一份
虽然我没有找到警告的全部逻辑。1. 2. 3. 应该被视为相同的 IMO(没有当前等效的警告,或者警告以备将来证明)。
对于 1.
复制和移动构造函数由编译器生成。
复制或移动最后得到相同的结果。
2.
Field
不再生成移动构造函数,使整个链复制而不是移动。
复制或移动最后得到相同的结果。
3.
Base
不再生成移动构造函数,从头开始复制。
复制或移动最后得到相同的结果。
对于 4.
Base 具有复制和移动构造函数。
复制或移动给出不同的结果。
为 5。
我们现在有匹配项 XXX(Derived&&)
(XXX
=Derieved
),因此没有完成复制。