C++11
我在使用 move 构造函数时遇到问题。我有一个简单的容器类,名为 Number
,其唯一的数据成员是整数。我有以下代码:
//Number.h
#ifndef NUMBER_H
#define NUMBER_H
#include <iostream>
class Number
{
public:
Number();
Number(int ipar);
Number(const Number& src);
Number(Number&& src);
private:
int num;
};
#endif
和
//Number.cpp
#include "Number.h"
Number::Number()
{
std::cout << "default ctor" << std::endl;
}
Number::Number(int ipar) : num(ipar)
{
std::cout << "integer argument ctor" << std::endl;
}
Number::Number(const Number& src) : num(src.num)
{
std::cout << "copy ctor" << std::endl;
}
Number::Number(Number&& src) : num(src.num)
{
std::cout << "move ctor" << std::endl;
}
和
//main.cpp
#include "Number.h"
using namespace std;
int main()
{
cout << "Part A:" << endl;
Number n1(1);
cout << "Part B:" << endl;
Number n2(n1);
cout << "Part C:" << endl;
Number n3{Number{n1}};
cout << "Part D:" << endl;
Number n4(Number(n1));
return 0;
}
输出:
Part A:
integer argument ctor
Part B:
copy ctor
Part C:
copy ctor
Part D:
请注意,D 部分没有输出。A 部分和 B 部分的输出符合我的预期,但其他部分的输出并非如此。
我预计 C 和 D 部分会这样:
Part C:
copy ctor
move ctor
Part D:
copy ctor
move ctor
对 C 部分的期望:
我期望 Number n3{Number{n1}}
的 Number{n1}
部分创建一个临时无名 Number
对象,因为通过使用 n1
调用复制构造函数,Number
和左大括号之间没有名称。然后我期望通过使用临时对象调用 move 构造函数来构造 Number n3
。
对 D 部分的期望:
由于这与 C 部分类似,只是使用圆括号而不是大括号,因此我希望该部分的行为和输出方式与我预期 C 部分相同。
问题:
为什么实际输出与我的期望不同?获得所需输出的正确方法是什么?
注意:如果您想在 Visual Studio 中编译此文件,则需要 Visual C++ Compiler November 2012 CTP或更高版本的 Visual Studio 2012,以支持统一的初始化语法。
最佳答案
n4
is a function declaration 。 n3
是由 copy elision 引起的.
检查 here我启用了 -fno-elide-constructors 以避免复制省略。 n3
然后显示一系列复制和 move 构造函数。
有一个注释掉的行尝试使用 n4
作为对象。如果取消注释它,您将看到编译器错误,告诉它是一个函数。
对于 n4
不要被解释为函数声明,您可以在临时变量周围放置额外的括号,以防止其被视为函数参数:Number n4((Number(n1) ))
。有了这个和 -fno-elide-constructors
你所期望的一切都会发生。
请注意,-fno-elide-constructors
在 MSVC 中不作为选项出现。
关于c++11 - 无法运行 move 构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15151765/