【问题标题】:What Constructor is being called, it's not move什么构造函数被调用,它不是移动
【发布时间】:2017-05-20 16:44:24
【问题描述】:

我创建了一个基本的测试类来了解移动构造函数的工作原理。移动构造函数似乎没有被调用,我不确定实际调用了什么构造函数。如果我使用 std::move 则调用移动构造函数,但常规 R 值实际上不会调用它。为什么会发生这种情况,实际调用的是什么构造函数?我正在使用 g++ 4.6.3

#include <iostream>
#include <cstring>

class Test
{
  int a;
  int b;
  int* c;

public:
  Test(int one, int two)
  {
    std::cout << "Param Constructor" << "\n";
    a = one;
    b = two;
  }

  Test()
  {
    std::cout << "Default Constructor" << "\n";
    a = 1;
    b = 2;
  }

  ~Test()
  {
    std::cout << "Deconstructor" << "\n";
  }

  Test(const Test& test)
  {
    a = test.a;
    b = test.b;
    std::cout << "Copy constructor called" << "\n";
  }

  Test(Test&& test)
  {
    std::cout << "Move constructor called" << "\n";
    a = test.a;
    b = test.b;
  }

  Test& operator=(const Test& test)
  {
    std::cout << "in operator=" << "\n";
    a = test.a;
    b = test.b;
    return *this;
  }
};

Test createTest()
{
  return Test(1,2);
}

int main()
{
  Test test(createTest());
  Test test2 = test;
  std::cout << "After logic" << "\n";
  return 0;
}

我得到的输出:

Param Constructor
Copy constructor called
After logic
Deconstructor
Deconstructor

我创建了一个名为 test 的类型为 Test 的对象,但没有创建它的输出?我期待这个输出:

Param Constructor
Move Constructor // (Missing)
Deconstructor //Deleting instance from createTest (Missing)
Copy constructor called
After logic
Deconstructor
Deconstructor

【问题讨论】:

  • 复制省略。使用-fno-elide-constructors 编译。
  • 这实际上说明了一个非常棒的观点:调用std::move 在某些情况下实际上可能是有害的。特别是,在函数内部的 return 语句的值上调用它,或者在调用范围内的函数调用返回时调用它。无论如何,这两个东西都已经是右值,所以没有任何好处。但正如您所见证的,它实际上可以防止复制省略。移动构造函数可能比复制构造函数更好,但是 no 构造函数调用是最快的:-)

标签: c++ c++11


【解决方案1】:

实际调用的是什么构造函数?

根本没有构造函数。计算析构函数调用的次数。你会发现比你预期的少一个。根本没有创建您期望构建的临时对象。

为什么会这样

编译器避免创建临时。取而代之的是,该对象被构建在它本来应该被移动到的地方。这称为复制省略。

【讨论】:

  • 很好的答案,谢谢:)。我将研究一下复制省略。
猜你喜欢
  • 2015-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-25
  • 2016-07-12
  • 2012-04-29
相关资源
最近更新 更多