1

The copy constructor has been provided. While using it exactly same type is passed to argument. Still the it seems the compiler( gcc/g++ 4.8.2) ignores existence of explicit copy constructor. The code generates compilation error. Why? The error is:

t.cpp: In function ‘A f(const A&)’:
t.cpp:19:12: error: no matching function for call to ‘A::A(const A&)’
     return a;  //compilation error with gcc 4.8.2
            ^
t.cpp:19:12: note: candidate is:
t.cpp:14:5: note: A::A()
     A(){}
     ^
t.cpp:14:5: note:   candidate expects 0 arguments, 1 provided
t.cpp:21:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

I have already gone through
Why I am not able to invoke 'explicit a (string x)'? and Explicit copy constructor. Based on the those links and i have tried the forcing copy construction (to avoid optimization,Refer to my commented code).

#include <iostream>
using namespace std;

class A 
{
public:
    explicit A(const A& a)   // an explicit copy constructor
    //A(const A&)   // an copy constructor, pretty much default one. 
                    //using it solves any compile problem.
    {
        cout << "\nin the copy constructor" << endl;
    }

    A(){}
};
//////////////////////////////////
A f(const A &a)
{   
    return a;  //compilation error with gcc 4.8.2
    //return A(a);   // even tried this to avoid optimization. does not work 
}
///////////////////////////////////
int main()
{
    //A a;
    //f(a);  
    return 0;
}
Community
  • 1
  • 1
qqqqq
  • 837
  • 12
  • 31
  • Why do you need an explicit copy constructor? – leewz Dec 06 '13 at 18:51
  • Maybe turning on some optimization levels will make the copy go away. – leewz Dec 06 '13 at 18:55
  • I am not trying to achieve anything here by the program. It is meant for better understanding of copy constructor itself. – qqqqq Dec 06 '13 at 19:03
  • Sorry, turning on the optimizations MIGHT make the copy go away if the constructor were not explicit, but using an explicit constructor implicitly will still be syntactically incorrect and thus it still won't compile. – leewz Dec 06 '13 at 19:12
  • 1
    You mention that ***"The code generates compilation error."***, but I don't see that you actually mentioned what the error is. Errors generally have really good information in the text. Please post the ***exact*** compilation error. – abelenky Dec 06 '13 at 19:15
  • I believe I am providing exact data type ( const A & ) . What are "from" and "to" data-types that you see in the implicit conversion(if any implicit conversion is taking place at all). – qqqqq Dec 06 '13 at 19:20
  • Doesn't my answer explain where the implicit copy is? Your return type is `A` rather than `A&` or `A const&`, and `A` means "return by copy". – leewz Dec 06 '13 at 19:49
  • Sorry. I am unable to understand you. As you said. It has to return "A". Then it should look for all the construtors of A. The compilers complains no matching function for call to ‘A::A(const A&)’, while exactly that constructor is there! – qqqqq Dec 06 '13 at 21:11
  • It has to return by copy, because of your return type. It needs implicit copy. I agree, that's a bad error message. – leewz Dec 06 '13 at 22:31

1 Answers1

3

The copy constructor is called implicitly on return (and also when passing an argument by value).

This code would call the copy constructor twice:

A f(const A &a)
{   
    return A(a);
}

The A(a) means an explicit copy, and then there is an implicit copy on return.

If you want to disallow implicit copying, then you can't return by copy, either. You'll have to return by reference or pointer (probably with a new'd copy).


In C++11 and up, I believe that the code above would instead call the move constructor (if defined) for the return (though it would still call the copy constructor for the explicit call), and that should be more efficient.

leewz
  • 3,201
  • 1
  • 18
  • 38
  • +1 *"The `A(a)` means an explicit copy, and then there is an implicit copy on return."* The Standard talks about *copying into the function's return value* (or moving). I.e. the copy is done from the temporary created via `A(a)` into the temporary returned from the function `f`. This happens as the expression in the return-statement is implicitly converted to the return type; this conversion is copy-initialization, which requires a non-explicit ctor. – dyp Dec 06 '13 at 19:41
  • The use of term "copy-initialization" in "DyP" comment led me to understanding it. I searched on internet and found: Copy initialization is performed in the following situations: 1) when a named variable (automatic, static, or thread-local) is declared with the initializer consisting of an equals sign followed by an expression. 2) when passing an argument to a function by value 3) Copy-initialization is less permissive than direct-initialization: copy-initialization only considers non-explicit constructors and user-defined conversion functions. – qqqqq Dec 06 '13 at 21:29