C++ 是否保证在返回时移动临时对象的子对象?

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

gcc 6.2和clang 3.8输出相同:

建造

复制构造

破坏

破坏


返回本地对象时,将不使用复制或移动,而是使用复制省略,这是优于移动的。这是因为控制本地对象的复制省略和移动的规则是相同的。而是通过显式使用
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
}