C++ 是否保证在返回时移动临时对象的子对象?
gcc 6.2和clang 3.8输出相同: 建造 复制构造 破坏 破坏C++ 是否保证在返回时移动临时对象的子对象?,c++,c++11,standards,move-semantics,C++,C++11,Standards,Move Semantics,gcc 6.2和clang 3.8输出相同: 建造 复制构造 破坏 破坏 返回本地对象时,将不使用复制或移动,而是使用复制省略,这是优于移动的。这是因为控制本地对象的复制省略和移动的规则是相同的。而是通过显式使用std::move强制移动时,如中所示 #include <iostream> struct A { A() { std::cout << "constructed\n"; } A(const A&) { std::cout <&l
返回本地对象时,将不使用复制或移动,而是使用复制省略,这是优于移动的。这是因为控制本地对象的复制省略和移动的规则是相同的。而是通过显式使用
std::move
强制移动时,如中所示
#include <iostream>
struct A
{
A() { std::cout << "constructed\n"; }
A(const A&) { std::cout << "copy-constructed\n"; }
A(A&&) { std::cout << "move-constructed\n"; }
~A() { std::cout << "destructed\n"; }
};
struct B
{
A a;
};
A f()
{
B b;
return b.a;
}
int main()
{
f();
}
模板
std::string make_string(T const&x)
{
std::ostringstream str;
str关于“隐含移动”规则最清晰的表述是在当前工作文件的第1部分:
在以下复制初始化上下文中,可能会执行移动操作
用于替代复制操作:
- 如果返回语句([stmt.return])中的表达式是用
正文中声明的自动存储持续时间或
最内层封闭函数或lambda表达式的参数声明子句,或
- [……]
选择副本构造函数的重载解析是第一个
就像对象由右值指定一样执行。如果
重载解析失败或未执行,或者
所选构造函数的第一个参数不是右值引用
对于对象的类型(可能是cv限定),重载解析为
再次执行,将对象视为左值
b.a
和coll[0]
都不是id表达式。因此,没有隐式移动。如果要移动,则必须显式移动。“那么coll
保证在返回时移动。”不,不是。副本可能会被省略,在这种情况下,没有移动。您没有使用f()的返回值那么要移动什么呢?左值可以移动的条件与复制省略紧密耦合(参见我的答案)。不。gcc 6.2和clang 3.8都没有在我的原始示例中执行复制省略。参见我的更新。
#include <iostream>
struct A
{
A() { std::cout << "constructed\n"; }
A(const A&) { std::cout << "copy-constructed\n"; }
A(A&&) { std::cout << "move-constructed\n"; }
~A() { std::cout << "destructed\n"; }
};
struct B
{
A a;
};
A f()
{
B b;
return b.a;
}
int main()
{
f();
}
template<typename T>
std::string make_string(T const& x)
{
std::ostringstream str;
str << x
return std::move(str.str()); // not recommended
}