【问题标题】:Different behaviour based on move constructor [duplicate]基于移动构造函数的不同行为[重复]
【发布时间】:2021-10-13 21:49:20
【问题描述】:

我有一段代码可以检查move 是否发生。

struct Foo
{
  Foo() = default;
  Foo(Foo&& other) = default;

  double a[1000];
  double b[1000];
};

Foo giveMe()
{
  Foo ret;
  std::cout << &ret << std::endl;

  return ret;
}

int main()
{
  Foo o1 = giveMe();
  std::cout << &o1 << std::endl;

  return 0;
}

好吧,事实并非如此。例如reto1的地址如下:

008F7D78
008FBC08

但是,在移动构造函数稍作改动后:

struct Foo
{
  Foo() = default;
  Foo(Foo&& other) {}

  double a[1000];
  double b[1000];
};

收件人相同:

010FBE28
010FBE28

这里发生了什么?我认为这种行为在某种程度上与 PODtrivial 类型有关,但我不确定如何。

【问题讨论】:

  • “移动”意味着将资源从一个实例移动到另一个实例。不要将实例移动到另一个内存地址。
  • @churill 我知道。地址检查只是为了查看是否发生了移动或复制。
  • 依赖于编译器,编译flags。
  • "稍作改动后" 第一个 sn-p 移动(因此复制此类型)成员,而第二个 sn-p 不初始化成员。
  • @tucna 我认为你对搬家有一点误解。想象一下Foo a; Foo b(std::move(a)); 这将调用 move-ctor 但两个对象将具有不同且恒定的地址。并考虑到静态数组永远不能移动,只能复制,所以你的 move-ctor 和 copy-ctor 一样。

标签: c++ struct move


【解决方案1】:

这里发生了什么?

这里正在进行优化。更准确地说:命名返回值优化 (NRVO)。

尽管抽象机在这两种情况下都会移动,但 NRVO 优化(省略)了第二个示例的移动。

地址检查只是为了查看是否发生了移动或复制。

该类不可复制,因此不可能发生复制。此外,地址检查无法区分复制和移动的对象。两者都有不同的地址。

澄清一个可能的误解:“移动”构造使用移动构造函数创建一个新对象。新对象的地址通常与被移动的对象不同,就像复制时一样。新对象的地址相同的唯一情况是移动被优化,使得构造函数永远不会被实际调用(这也可以通过副本来完成)。

【讨论】:

    猜你喜欢
    • 2011-05-22
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多