Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how can I find where a C++ copy constructor is being USED via a compile error?

In short: is there some way I can modify a class definition such that it fails to compile at the point of use of a copy constructor no matter where it's used?

I have a very large project and was cleaning up some class definitions. There's a class that I explicitly don't want to use copy constructors on (let's ignore why that is for the sake of this discussion), and in the interest of safety, I figured I'd just define the copy constructor as private and not actually implement it... that way it would throw a compile error if I tried to use it anywhere. Lo and behold, it compiles fine, but I have a linker error... the copy constructor implementation is not found! Presumably that means it's in use somewhere, but I'm unable to find where it's being used. This is Visual Studio 2010 by the way. So my question is, is there some way I can modify the class definition such that it fails to compile at the point of use?

class Sample {
private:
    // not implemented
    Sample( const Sample& rhs );
    Sample& operator=( const Sample& rhs );
public:
    // implemented
    Sample();
...
};

Sample *samp1 = new Sample;
Sample *samp2 = new Sample( *samp1 ); // <<-- inaccessible here!  this works

Presumably since I'm not hitting a compile error, but am hitting the linker error, that it means the class itself (or a friend) is doing the copy-constructed create (since that's all that would have access to the private constructor), but I sure can't find it!

like image 549
mark Avatar asked Jan 27 '12 17:01

mark


People also ask

What are the situations where a copy constructor is invoked?

In C++, a Copy Constructor may be called for the following cases: 1) When an object of the class is returned by value. 2) When an object of the class is passed (to a function) by value as an argument. 3) When an object is constructed based on another object of the same class.

Is copy constructor automatically created by compiler?

The compiler also creates a copy constructor if we don't write our own copy constructor. Unlike the default constructor, the body of the copy constructor created by the compiler is not empty, it copies all data members of the passed object to the object which is being created.

Why is my copy constructor not being called?

The reason the copy constructor is not called is because the copy constructor itself is a function with one parameter. You didn't call such function,so it didn't execute.

Does the compiler always provide a default copy constructor?

In C++, the compiler automatically generates the default constructor, copy constructor, copy-assignment operator, and destructor for a type if it does not declare its own. These functions are known as the special member functions, and they are what make simple user-defined types in C++ behave like structures do in C.


2 Answers

in C++11 you can change the definition to

class Sample {
private:
    // not implemented
    Sample( const Sample& rhs ) = delete;
    Sample& operator=( const Sample& rhs ) = delete;
public:
    // implemented
    Sample();
...
};

prior to C++11 this is usually done by inheritting from a class that declares a private copy constructor such as boost::NonCopyAble (you can simply copy this class, it's only a few lines). In this case your class (or any friends or children) also cannot access the copy constructor and it will generate a compile-time error.

like image 98
KillianDS Avatar answered Oct 21 '22 07:10

KillianDS


Inherit from a noncopyable class:

class noncopyable
{
private:
    // not implemented
    noncopyable( const noncopyable& rhs );
    noncopyable& operator=( const noncopyable& rhs );
};


class Sample : private noncopyable {
private:
    // not implemented

    Sample( const Sample& rhs );
    Sample& operator=( const Sample& rhs );
public:
    // implemented
    Sample();

    // ...
};

Sample *samp1 = new Sample;
Sample *samp2 = new Sample( *samp1 ); // <<-- compile-time error

This works fine even if you don't have C++11 (where the delete method mentioned elsewhere is probably preferable).

like image 33
Michael Burr Avatar answered Oct 21 '22 06:10

Michael Burr