What's the Use of the Private Copy Constructor in C++

What's the use of the private copy constructor in c++

Some objects represent particular entities that can't or shouldn't be copied. For example, you may prevent copying of an object that represents the log file used by an application, corresponding to the expectation that a single log file will be used by all parts of the code. Use of an accidentally or inappropriately copied object could lead to out-of-order content appearing in the log, inaccurate records of current log size, multiple attempts (some failing) to "roll" to a new log filename or rename the existing one.

Another use is to enforce copying via a virtual function. As constructors can't be virtual, a common practice is to prevent direct access to the copy constructor and provide a virtual Base* clone() method that returns a copy of the actual run-time type to which a pointer points. This prevents the accidental slicing that Base b(derived) would exhibit.

Another example: a dead-simple smart pointer object that simply deletes the pointer it's given in the constructor: if it doesn't support reference counting or some other manner of handling multiple owners, and doesn't want to have risk awkward unintended std::auto_ptr style transfer of ownership, then simply hiding the copy constructor gives a great little smart pointer that's fast and efficient for the limited cases where it's usable. A compile time error about attempting to copy it would effectively ask the programmer "hey - if you really want to do that change me to a shared pointer, otherwise back off!".

Why use private copy constructor vs. deleted copy constructor in C++

2 possible reasons:

  • you cannot use C++11 or later

  • you need objects of the class to be copyable by methods of the class or it's friends, but not by anything else

Can I make the copy constructor private and still use the default implementation

Is this possible without rewriting the copy-ctors definition ?

In C++11, yes. You just have to declare the constructor and mark it as defaulted:

struct X
{
// ...
private:
X(X const&) = default;
};

This will define a copy constructor which would have the same definition as an implicitly generated one, but will be private. For instance:

struct X
{
X() { } // Required because a user-declared constructor in
// the definition of X inhibits the implicit generation
// of a default constructor (even if the definition is
// defaulted!)

void foo()
{
// ...
X tmp = *this; // OK!
// ...
}

private:

X(X const&) = default; // Default definition, accessible to
// member functions of X only!
};

int main()
{
X x;
// X x2 = x; // ERROR if uncommented!
}

Here is a live example.

Notice, that a user-declared constructor (including copy constructor) in a class definition inhibits the implicit generation of a default constructor, even if its definition is defaulted. This is why, for instance, I had to explicitly declare X's default constructor in the example above.

Why would I make copy constructor and assignment operator private and implemented in C++?

There are two cases that come to mind immediately:

  1. friends:

    Say that, as part of your design, you have two highly coupled classes where one needs to be able to copy the other (say, as in a factory model or some such), but you don't want to let the whole world be able to copy it.

  2. wrappers:

    Say you want to be able to conditionally clone some element, depending on some internal behavior (e.g., depending on some class-stateful condition) - the cleanest way, from a language perspective - is still to separate the copying into its own function. This would allow for good separation of concerns.

Should copy constructor be private or public

The copy constructor should be private if you do not want objects of the class to be copied. Otherwise, it should be public.

How to create an array with Object that has private copy constructor

You'll have to define the move ctor and move assignment operator on the Image class since the default implementations would be deleted because you provided a user declared copy ctor and copy assignment operator.

You should then be able to use the vector with no issue.

class Image
{
public:
Image( int height, int width )
: height_{ height }
, width_{ width }
{ }

Image( Image&& ) = default;
Image& operator=( Image&& ) = default;

Image( const Image& ) = delete;
Image& operator=( const Image& ) = delete;

private:
int height_;
int width_;
};

class ImageInformation
{
public:
explicit ImageInformation( Image image )
: image_{ std::move( image ) }
{ }

private:
Image image_;
};

int main( )
{
std::vector<ImageInformation> containers;

Image image{ 10, 10 };
containers.emplace_back( std::move( image ) );
}

Why can I access private variables in the copy constructor?

IMHO, existing answers do a poor job explaining the "Why" of this - focusing too much on reiterating what behaviour's valid. "access modifiers work on class level, and not on object level." - yes, but why?

The overarching concept here is that it's the programmer(s) designing, writing and maintaining a class who is(are) expected to understand the OO encapsulation desired and empowered to coordinate its implementation. So, if you're writing class X, you're encoding not just how an individual X x object can be used by code with access to it, but also how:

  • derived classes are able to interact with it (through optionally-pure virtual functions and/or protected access), and
  • distinct X objects cooperate to provide intended behaviours while honouring the post-conditions and invariants from your design.

It's not just the copy constructor either - a great many operations can involve two or more instances of your class: if you're comparing, adding/multiplying/dividing, copy-constructing, cloning, assigning etc. then it's often the case that you either simply must have access to private and/or protected data in the other object, or want it to allow a simpler, faster or generally better function implementation.

Specifically, these operations may want to take advantage of priviledged access to do things like:

  • (copy constructors) use a private member of the "rhs" (right hand side) object in an initialiser list, so that a member variable is itself copy-constructed instead of default-constructed (if even legal) then assigned too (again, if legal)
  • share resources - file handles, shared memory segments, shared_ptrs to reference data etc.
  • take ownership of things, e.g. auto_ptr<> "moves" ownership to the object under construction
  • copy private "cache", calibration, or state members needed to construct the new object in an optimally usable state without having to regenerate them from scratch
  • copy/access diagnostic/trace information kept in the object being copied that's not otherwise accessible through public APIs but might be used by some later exception object or logging (e.g. something about the time/circumstances when the "original" non-copy-constructed instance was constructed)
  • perform a more efficient copy of some data: e.g. objects may have e.g. an unordered_map member but publicly only expose begin() and end() iterators - with direct access to size() you could reserve capacity for faster copying; worse still if they only expose at() and insert() and otherwise throw....
  • copy references back to parent/coordination/management objects that might be unknown or write-only for the client code

Private copy constructor with unamed argument?

The & indicates pass by reference when used in argument definitions. This converts the argument into a pointer and de-references that pointer when you use it within the function scope. In your second question both functions print the same thing because the & simply says pass the original object by reference instead of copying it into the function header. The same content exists, the only difference is one of the functions copies the full input and the other could edit the source variable if it wanted to.

CPU (const CPU&){} is saying the constructor requires a constant reference to a CPU object. This means you can only access const functions of CPU (and guarentee you won't change the original CPU object argument). Not having a name after the CPU& just means you're not assigning the variable to a name within the current scope (aka the brackets after the definition will ignore the argument).

When a constructor is private it usually means there's another function which will generate the Object for you. Factories will oftentimes hide an objects constructor and require some other attributes/registration before building the object for you.



Related Topics



Leave a reply



Submit