6

I was checking operator overloading in C++ and came across something I did not expect and have some doubts about it.

My copy constructor is declared and implemented as as

explicit Vector(const Vector& v);

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

then I am overloading the compound assignment operators

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;
}

however, in the return statements I got an error saying no matching constructor for initialization of 'Vector'.

Since the only thing I added to my constructor was the explicit keyword, I deleted it and the code compiles just fine, why?

I also was checking new stuff from C++11 and occurred that I can declare my constructor like a moving-constructor

explicit Vector(const Vector&& v);

and the code compiles just fine. If I do that, do I have to have both copy and move constructors?

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

or just having the move constructor will work fine? If I want to stick to C++11, what is the correct approach to follow?

5
  • possible duplicate of Explicit copy constructor Commented Apr 6, 2015 at 13:54
  • More than likely += and -= are making an implicit copy causing the error. Commented Apr 6, 2015 at 13:56
  • Not an answer but a comment on your code. There is no reason to define such a copy constructor at all, as the default ones will do exactly the same. There is also usually on reason to declare a copy constructor explicit, as its putpose is to prevent implicit type conversions. Commented Apr 6, 2015 at 14:00
  • @MikeMB "declare a copy constructor explicit, as its putpose is to prevent implicit type conversions" such as? Commented Jun 13, 2018 at 6:12
  • 1
    @curiousguy: Sorry, badly worded: Should read "There is also usually no reason to declare a copy constructor explicit, as its [the explicit keyword] purpose is to prevent implicit type conversions." which is not what is happening when making a copy. Commented Jun 13, 2018 at 8:12

2 Answers 2

5

You defined an explicit copy constructor, but the functions

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

and

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

must return by value, and cannot anymore, due to explicit (in other words, they cannot copy tmp into the returned object).

I also was checking new stuff from C++11 and occurred that I can declare my constructor like a moving-constructor explicit Vector(const Vector&& v); and the code compiles just fine. If I do that, do I have to have both copy and move constructors?

Not sure I understand what you mean here. You will have the same issue if you only declare an explicit move constructor (which will prevent the compiler from generating a default copy constructor). I am not able to produce a "compilable" code.

Sign up to request clarification or add additional context in comments.

8 Comments

I think I messed things up. The returned value, is it an lvalue or an rvalue? If it is an rvalue, couldn't I, instead of copying tmp, use the move constructor or move operation that is new in C++11?. If it is an lvalue will the function always copy the value? is there any optimization from the compiler?
@BRabbit27 the return is a rvalue, and the compiler performs the optimization whenever possible (it is called return value optimization, or RVO). However, if you declare the move/copy constructors explicit, even if the optimization is in principle possible, the compiler still complains about the explicit business. That's mainly because the compiler first performs correctness analysis of your program, then applies optimizations. The code should be valid C++ before the optimization phase.
@BRabbit27 and in C++11, the compiler first tries to move the returned object (if possible), if not, it looks for a copy constructor to copy it, and if it still doesn't find one it emits an error. That's the case here, you don't have any implicit copy/move constructors.
So, I guess the question to ask is: when should I use explicit in a constructor? If I just don't put the explicit keyword there my code should be fine in terms of compiling and best practices?
@BRabbit27 the idea is that if you marked the copy ctor explicit, then the complier wants to "see" a direct invocation of it, like Foo copy(original), not like Foo copy = original. The latter case is an implicit copy. The same happens when passing/returning to/from a function, you don't "see" the copy constructor spelled out in the code, so the copy is implicit. Because of that, explicit forbids it.
|
0

Returning an object by value requires that an implicit copy construction can be performed. Making the copy constructor explicit prevents that.

This is true whether or not the compiler elects not to invoke the copy constructor (e.g. the return value optimisation).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.