C++ 在没有移动构造函数的情况下,是否调用复制构造函数?为什么呢?
我正在读C++11,我有以下问题。假设我有以下粗略的代码C++ 在没有移动构造函数的情况下,是否调用复制构造函数?为什么呢?,c++,c++11,move-constructor,C++,C++11,Move Constructor,我正在读C++11,我有以下问题。假设我有以下粗略的代码 class foo { public: foo() {std::cout << "Regular constructor \n";} foo(const foo& a) {std::cout << "Copy constructor \n";} foo& operator=(const foo& a) {std::cout <&l
class foo
{
public:
foo()
{std::cout << "Regular constructor \n";}
foo(const foo& a)
{std::cout << "Copy constructor \n";}
foo& operator=(const foo& a)
{std::cout << "Copy Assignment operator \n";}
foo(foo&& a)
{
std::cout << "Move constructor \n";
}
foo& operator=(foo&& a)
{std::cout << "Move Assignment operator \n";}
int a;
};
foo myfunction()
{
foo d;
d.a =120;
return d;
}
我知道会调用move构造函数,因为myfunction()返回一个右值类型。
现在我注意到,如果我从类中删除move构造函数代码,那么就会调用copy构造函数。我的问题是为什么会这样?如果myfunction的返回类型是foo&&并且复制构造函数接受foo&那么为什么要调用复制构造函数?我正在使用Vs2012
如果myfunction的返回类型是foo&
但事实并非如此!返回类型为foo
。并且constfoo&
愉快地绑定到foo
rvalue
提示:“右值”和“右值引用”是两个相关但不同的概念。(请记住,C++在RValk引用被引入语言之前已经有几十年的值了)。 如果类
X
的定义没有显式声明移动构造函数,则当且仅当
-X
没有用户声明的复制构造函数,-
X
没有用户声明的复制分配运算符,-
X
没有用户声明的移动分配运算符,并且-
X
没有用户声明的析构函数
因为您有一个用户声明的复制构造函数,所以移动构造函数是不可访问的,它会返回到调用复制构造函数
如果myfunction
的返回类型是foo&
并且复制构造函数接受foo&
的值,那么为什么要调用复制构造函数
这里有两个错误:
myfunction
按值返回foo
,而不是foo&
。此外,您的构造函数采用constfoo&
,它实际上可以绑定到右值(这里并不是这样)。为了进一步阅读,.当你说时,你的构造函数采用const foo&它实际上可以绑定到右值
,你能再解释一下吗?@Rajeshwar你说你的构造函数采用foo&
,这不是真的。你把它写成foo(constfoo&)
。该语言允许右值绑定到const
(即int-const&r=100
)的引用。但是从myfunction
返回的值是左值,而不是右值。感谢您的澄清。现在我不明白为什么在fooa=myfunction()的情况下调用move构造函数(如果存在的话)
是否从函数返回左值?@Rajeshwar否,我说返回值d
是左值。它是由返回类型foo
复制构建的myfunction
按值返回,因此返回的是临时值(右值)。如果移动构造函数可用且可行,则会选择它来初始化a
,因为它比复制构造函数(即右值)更匹配。请解释一下。const-foo&愉快地绑定到一个foo-rvalue。
更详细一点。您是否声明函数实际上返回一个被移动构造函数首先捕获的foo&
类型?foo
绑定到const foo&
,如果它不是临时的,或者绑定到foo&
。如果编译器确实在返回时复制优化,那么实际上您正在用d
初始化fooa
,它有一个名称(因此不是临时的)@Rajeshwar我不知道您在问什么。在C++中,如果你按值返回,那么你就有一个rValst,const引用总是能够绑定到它们。“右值”并不意味着“右值引用”或“移动构造函数”。
foo a = myfunction();