2015-04-06 77 views
6

我检查C++操作符重载和横跨东西,我没想到的,并有一些关于它的质疑来了。明确的拷贝构造函数编译出错

我的拷贝构造函数声明并实现为

explicit Vector(const Vector& v); 

Vector::Vector(const Vector& v) : 
_x(v._x), _y(v._y), _z(v._z) {} 

那么我超载了复合赋值运算符

Vector Vector::operator+(const Vector& v) const 
{ 
    Vector tmp(*this); 
    tmp += v; 
    return tmp; 
} 

Vector Vector::operator-(const Vector& v) const 
{ 
    Vector tmp(*this); 
    tmp -= v; 
    return tmp; 
} 

然而,在return声明我得到一个错误说no matching constructor for initialization of 'Vector'

自从我加入到我的构造函数中的唯一的事情就是explicit关键字,我删除它和代码编译就好了,为什么呢?

我也从C++ 11检查新的东西和发生,我可以宣布我的构造就像一个移动的构造函数

explicit Vector(const Vector&& v); 

和代码编译就好了。如果我这样做,我必须同时复制和移动构造函数吗?

explicit Vector(const Vector& v); 
explicit Vector(const Vector&& v); 

或只是有移动构造函数会正常工作?如果我想坚持使用C++ 11,那么遵循的正确方法是什么?

+0

[显式拷贝构造函数]可能的重复(http://stackoverflow.com/questions/11480545/explicit-copy-constructor) – Predelnik 2015-04-06 13:54:52

+0

很可能'+ ='和' - ='正在创建隐式拷贝,导致错误。 – NathanOliver 2015-04-06 13:56:49

+0

不是答案,而是对您的代码的评论。根本没有理由定义这样的复制构造函数,因为默认的构造函数完全一样。通常也有理由声明复制构造函数是明确的,因为它的目的是防止隐式类型转换。 – MikeMB 2015-04-06 14:00:06

回答

5

你定义一个明确的拷贝构造函数,但功能

Vector Vector::operator+(const Vector& v) const 

Vector Vector::operator-(const Vector& v) const 

必须通过值返回,并且再也看不到了,因为explicit(换句话说,他们不能复制tmp进入返回的对象)。

我也从C++ 11检查新的东西和发生,我可以宣布我的构造就像一个移动的构造函数 explicit Vector(const Vector&& v);和代码编译就好了。如果我这样做,我必须同时复制和移动构造函数吗?

不知道我理解你的意思在这里。如果你只声明一个显式的移动构造函数(这会阻止编译器生成一个默认的复制构造函数),你将会遇到同样的问题。我无法制作“可编译”代码。

+0

我想我搞砸了。返回的值是左值还是右值?如果它是一个** rvalue **,我不能,而不是复制'tmp',使用C++ 11中新增的移动构造函数或移动操作。如果它是一个**左值**该函数将始终复制该值?编译器有没有优化? – BRabbit27 2015-04-06 14:43:05

+3

@BRabbit27返回值是一个右值,编译器会尽可能地执行优化(它被称为*返回值优化*或RVO)。然而,如果你声明移动/拷贝构造函数是“显式”的,即使原则上可能进行优化,编译器仍然抱怨“显式”业务。这主要是因为编译器首先执行程序的正确性分析,然后应用优化。在优化阶段之前,代码应该是有效的C++。 – vsoftco 2015-04-06 14:51:04

+1

@ BRabbit27在C++ 11中,编译器首先尝试移动返回的对象(如果可能的话),如果不是,它会查找复制构造函数以复制它,如果它仍然没有找到,它会发出错误。在这种情况下,您没有任何隐式复制/移动构造函数。 – vsoftco 2015-04-06 14:52:37

0

通过返回值的对象,需要能够执行一个隐含的复制结构。使复制构造函数显式阻止。

这是真正的编译器是否选择不调用拷贝构造函数(例如,返回值优化)。