(The avoidance of) Copy mechanics in C++ [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why copy constructor and assignment operator are disallowed?
I'm learning C++ from a solid C background, and in the eagerness to avoid the errors of previous C++ that I gleaned from reddit and hacker news, I've been using the Google C++ style guide and LLVM's source code as references for my own code. One thing that sticks out is both the projects' use of the following code. The following is taken from LLVM's include/Support/MemoryBuffer.h:
MemoryBuffer(const MemoryBuffer &); // DO NOT IMPLEMENT
MemoryBuffer &operator=(const MemoryBuffer &); // DO NOT IMPLEMENT
Google echoes this usage. Clearly, it's a good thing to disable these "copy constructors".
So my question is: why are these things so scary, and (if they are not guarded against) what does their use look like and what effect does it cause in code?

When an object has to manage its own resources, such as memory or a system handle, then the default copy constructor and assignment operator are no longer appropriate. That means you have to override them.
However, sometimes it doesn't make any sense to copy such an object. Or, said differently, some objects are not meant to be copied. Sometimes it's not even possible to write such a constructor or assignment operator. In that case, it's best to disable copy and assignment to make sure they're not copied by accident.
The standard's iostream are a good example.
All in all, it's a, say, special case. Definitely not something you would encounter often.

There is nothing scary about copy-constructors and they should not be viewed as such.
However, that said, there are times where copying an object simply doesn't make sense. In the example you provided, a memory buffer is a good example of something that makes no sense to copy. It has perhaps been used to store the data of allocated objects. What does a copy provide? A duplicate of the raw data of all those objects and not much else (the objects can't use it to de-allocate with, for example).
So, once we have decided that it makes no sense to copy our class, it also makes sense that we should prevent the programmer from doing it. The compiler will be sneaky and make default copy constructors and assignment operators for us, if we don't declare them ourselves. So, if we DO declare them (we don't need to provide an implementation) and make sure those declarations are private, then the compiler will issue a compile-error if the programmer attempts to do just that.

In C++03, declaring a copy constructor and assignment operator with no definition as private is a way to prevent people from being able to copy instances of your class. If anyone attempts to do so, they'll get a compile error complaining that the assignment operator and copy constructor are private. Additionally by providing no definition if the class's own methods try to use the functions they will get a linker error complaining the operator and copy constructor are not defined. This is necessary because otherwise the compiler will generate a copy constructor and assignment operator for you, which often will not do what you want (a shallow copy).
In the new C++11 standard, there is a better way to do this. The delete keyword can be used in declarations like so:
struct NoCopy
{
NoCopy & operator =( const NoCopy & ) = delete;
NoCopy ( const NoCopy & ) = delete;
};
NoCopy a;
NoCopy b(a); //compilation error, copy ctor is deleted
Example taken from here.

Sometimes, making copies do not make sense (eg. a std::unique_ptr, a mutex object, or a database connection object, etc). Or making copies is inefficient, and you want to prevent this operation. Or implementing the copy constructor correctly is painful and fragile, and you'd prefer not to rely on its presence. Deleting the copy semantics is done by declaring the copy constructor private.
Another popular option is to inherit from boost::non_copyable.
The C++11 standard offers an alternative to the ubiquitous use of the copy constructor. This goes by the name of move semantics, and allows you to move objects instead of copying them. Move semantics pretty much always make sense: returning an object from a function moves it for instance. You can also explicitly move an object into some function taking its argument by value.
Note that C++11 in principle allows you to delete copy semantics in this way:
struct foo
{
foo(const foo&) = delete;
void operator=(const foo&) = delete;
};
instead of making them private, like in C++03.
Whenever I would have had to declare and implement a copy constructor, I nowadays find myself almost always disabling the copy semantics. With some habit, it makes sense: if copy semantics are not trivial, there is a chance that something is wrong with copying. One notable exception is reference counting though (see the class template std::shared_ptr).

Related

passing instances of objects in C++ class constructors (exit code 134) [duplicate]

I've read that The Rule of Three, What is The Rule of Three? is summarized as follows:
If you need to explicitly declare either the destructor, copy constructor or copy assignment
operator yourself, you probably need to explicitly declare all three of them.
My question is: In a C++ application, I have a class that manages resources (has a destructor that handles deleting pointers). I know that the application uses assignment operator all over the place, but I am absolutely certain that there is no usage in the application of a copy constructor, i.e., usage of the type Class c(..); Class d(c); so under these circumstances, am I still required to implement both an assignment operator and a copy constructor? Or will an assignment operator alone suffice? Is it possible that the assignment operator uses the copy constructor somehow?
Appreciate your thoughts.
If you know that the copy constructor won't be used, you can express that by making it private and unimplemented, thus:
class C
{
private:
C(const C&); // not implemented
};
(in C++11 you can use the new = delete syntax). That said, you should only do that if you're absolutely sure it will never be needed. Otherwise, you might be better off implementing it. It's important not to just leave it as is, as in that case the compiler will provide a default memberwise copy constructor that will do the wrong thing - it's a problem waiting to happen.
To some extent it depends on what the class is going to be used for - if you're writing a class that's part of a library, for instance, it makes much more sense to implement the copy constructor for consistency reasons. You have no idea a priori how your class is going to be used.
I am absolutely certain that there is no usage in the application of a copy constructor, i.e., usage of the type Class c(..); Class d(c)
Are you aware that the following code
Foo c;
Foo b = c;
invokes the copy constructor and NOT the assignment operator? I'd implement the copy constructor just to be safe.
In almost all cases, the compiler will generate these methods for you and you don't need to do anything. But, if implicitly generated copy constructor/assignment operator won't do what you want, and design-wise your class makes sense to be able to be copied, you should explicitly provide a copy ctor and assignment operator whether you use them both or not (as good practice).
If, design-wise, your class makes sense to be noncopyable, you can declare but not define the copy ctor/assignment op.

Rule of Three in C++

I've read that The Rule of Three, What is The Rule of Three? is summarized as follows:
If you need to explicitly declare either the destructor, copy constructor or copy assignment
operator yourself, you probably need to explicitly declare all three of them.
My question is: In a C++ application, I have a class that manages resources (has a destructor that handles deleting pointers). I know that the application uses assignment operator all over the place, but I am absolutely certain that there is no usage in the application of a copy constructor, i.e., usage of the type Class c(..); Class d(c); so under these circumstances, am I still required to implement both an assignment operator and a copy constructor? Or will an assignment operator alone suffice? Is it possible that the assignment operator uses the copy constructor somehow?
Appreciate your thoughts.
If you know that the copy constructor won't be used, you can express that by making it private and unimplemented, thus:
class C
{
private:
C(const C&); // not implemented
};
(in C++11 you can use the new = delete syntax). That said, you should only do that if you're absolutely sure it will never be needed. Otherwise, you might be better off implementing it. It's important not to just leave it as is, as in that case the compiler will provide a default memberwise copy constructor that will do the wrong thing - it's a problem waiting to happen.
To some extent it depends on what the class is going to be used for - if you're writing a class that's part of a library, for instance, it makes much more sense to implement the copy constructor for consistency reasons. You have no idea a priori how your class is going to be used.
I am absolutely certain that there is no usage in the application of a copy constructor, i.e., usage of the type Class c(..); Class d(c)
Are you aware that the following code
Foo c;
Foo b = c;
invokes the copy constructor and NOT the assignment operator? I'd implement the copy constructor just to be safe.
In almost all cases, the compiler will generate these methods for you and you don't need to do anything. But, if implicitly generated copy constructor/assignment operator won't do what you want, and design-wise your class makes sense to be able to be copied, you should explicitly provide a copy ctor and assignment operator whether you use them both or not (as good practice).
If, design-wise, your class makes sense to be noncopyable, you can declare but not define the copy ctor/assignment op.

In what scenarios should I expect to explicitly need to implement a move constructor and move assignment operator?

Given that a class actually is moveable, manually implementing the move constructor and move assignment operator for a class quickly become tedious.
I was wondering when doing so is actually a heavy, heavy, premature optimization?
For instance, if a class only has trivial POD data or members that themselves have move constructor and move assignment operator defined, then I'd guess that the compiler will either just optimize the shit out of the lot (in the case of PODs) and otherwise use the members' move constructor and move assignment operator.
But is that guaranteed? In what scenarios should I expect to explicitly need to implement a move constructor and move assignment operator?
EDIT: As mentioned below by Nicol Bolas in a comment to his answer at https://stackoverflow.com/a/9966105/6345, with Visual Studio 11 Beta (and before) no move constructor or move assignment operator is ever automatically generated. Reference: http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
If you find yourself implementing, any of:
destructor
copy constructor
copy assignment
Then you should be asking yourself if you need to implement move construction. If you "= default" any of the above, you should be asking yourself if you should then also "= default" the move members.
Even more importantly, you should be documenting and testing your assumptions, for example:
static_assert(std::is_nothrow_default_constructible<A>::value, "");
static_assert(std::is_copy_constructible<A>::value, "");
static_assert(std::is_copy_assignable<A>::value, "");
static_assert(std::is_nothrow_move_constructible<A>::value, "");
static_assert(std::is_nothrow_move_assignable<A>::value, "");
static_assert(std::is_nothrow_destructible<A>::value, "");
First, move semantics only help for classes that hold resources of any kind. "Flat" classes don't benefit from it at all.
Next, you should build your classes out of "building blocks", like vector, unique_ptr and the likes, that all deal with the nitty-gritty low-level detail of resources. If your class is done as such, you won't have to write anything at all since the compiler will generate the members correctly for you.
If you need to write a destructor for, say, logging, generation of move ctors will be disabled, so you need a T(T&&) = default; for compilers that support it. Otherwise, this is one of the only places were to write such a special member yourself (well, except if you write such a "building block").
Note that the logging in the destructor and constructor can be done an easier way. Just inherit from a special class that logs on construction / destruction. Or make it a member variable. With that:
tl;dr Let the compiler generate the special member for you. This also counts for copy constructor and assignment operator, aswell as the destructor. Don't write those yourself.
(Okay, maybe the assignment operators, if you can identify them as a bottle neck and want to optimize them, or if you want special exception safety or somesuch. Though, the "building blocks" should already provide all that.)
Do it every time the default behavior is undesirable or every time the default ones have been deleted and you still need them.
The compiler default behavior for move is call the member and base move. For flat classes / buil-in types this is just like copy.
The problem is typically present with classes holding pointers or value representing resources (like handle, or particular indexes etc) where a move requires to copy the values in the new place, but also to set the old place to some "null state value" recognizable by the destructor. In all other cases, the default behavior is OK.
The problem may also arise when you define a copy (and the compiler deletes the default move) or a move (and the compiler deletes the default copy), and you need them both. In these cases, re-enabling the default may suffice.
In what scenarios should I expect to explicitly need to implement a move constructor and move assignment operator?
Under the following cases:
When you are using Visual Studio 10 or 11. They implement r-value references, but not compiler generated move semantics. So if you have a type that has members that need moving or even contains a moveable type (std::unique_ptr, etc), you must write the move yourself.
When you might need copy constructors/assignment operators and/or a destructor. If your class contains something that made you manually write copy logic or needs special cleanup in a destructor, odds are good that you'll need move logic too. Note that this includes deleting copy mechanisms (Type(const Type &t) = delete;). If you don't want to copy the object, then you probably need move logic or to delete the move functions too.
As others have said, you should try to keep the number of types that need explicit move or copy mechanisms to a bare minimum. Put these in utility "leaf" classes, and have most of your classes rely on the compiler-generated copy and move functions. Unless you're using VS, where you don't get those...
Note: a good trick with move or copy assignment operators is to take them by value:
Type &operator=(Type t) { std::swap(*this, t); return *this; }
If you do this, it will cover both move and copy assignment in one function. You still need separate move and copy constructors, but it does reduce the number of functions you have to write to 4.
The downside is that you're effectively copying twice if Type is made of only basic types (first copy into the parameter, second in swap). Of course, you have to implement/specialize swap, but that's not difficult.
I'm sorry. I may have missed the point of your question. I'm taking your question to mean copy constructors.
Back in the 1990s when I learned C++, I was taught always to write a copy constructor when designing a class. Otherwise, and this may have changed with newer versions of the compiler, C++ will generate a copy constructor for you in the situations that require one.
That default copy constructor may not always work the way you want. This would especially be true if your class contains pointers, or you otherwise do not want the default byte-wise copy of a default copy constructor.
Finally, I was taught that by writing a copy constructor, you are taking exact control over how you want your class copied.
I hope this helps.

Am I violating Rule of three?

I recently read, Rule of three and am wondering if I am violating it?
In my GUI application, classes like MainFrame, Interface, Circuit, Breadboard etc. (class name are indicative) have a single instance of each of them. In their constructors, I have allocated some resources (memory), which I safely release in their destructors.
So I have defined only destructor, but not copy constructor and assignment operator.
I am sure I don't need them, but I am curious if I am violating the rule, and what can/should I do to follow it?
The rule of three is about dealing with all the Big Three, but that does not necessarily mean you'll have to define them if you don't want to. Either you provide them or you forbid them. What you shouldn't do is ignore them.
So I have defined only destructor, but not copy constructor and copy operator.
Am I violating Rule of three?
Yes, you are in violation of the rule. The compiler will generate a copy constructor and copy assignment operator, and since you allocate memory in the constructor and release in the destructor, these copies will have wrong semantics: they'll copy the pointers, and you will have two classes aliasing the same memory. The assignment won't even release the old memory, and simply overwrite the pointer.
Is this a problem?
If, like you imply, you don't make copies or assign to instances of those classes, nothing will go wrong. However, it's better to be on the safe side and declare (and don't even bother defining) the copy constructor and copy assignment operator private, so you don't invoke them accidentally.
In C++11 you can use the = delete syntax instead:
T(T const&) = delete; // no copy constructor
T& operator=(T const&) = delete; // no copy assignment
It depends a lot on you application logic and how the you have documented your interface classes to the users.
Normally, a good c++ programmer must be aware of rule of three (and a half if you know the "copy and swap idiom") and 5 and a 1/2 in case of c++11 (Move semantics).
If you class manages resource and if the same class is copyable (i.e copy ctor and assigment operator not defined as private) then its very important to do deep copying by writing your own copy ctor and assignment operator.
But If you are always toying your class by passing them as REFERENCE then better define a default copy ctor and assignment operator as private so that even if you pass by valy or copy by mistake, the compiler would warn you.
You should declare (but not implement) a private copy constructor and assignment operator. Make sure you don't implement the functions. This will prevent any kind of copying of classes not supposed to be copied.
Yes, it does violate the rule of three as per that definition.
It is, however, a "rule of thumb". A general guideline. If you don't need copy construction or assignment operations, don't implement them. Others have suggested declaring them as private and defining them as empty. I'd go one step further and say don't even define them.
If you define them, then you could potentially still invoke the empty methods. Instead, leave them undefined and, if you ever try to invoke those methods, you will receive a linker error because the method definitions could not be found. Favor build-time errors over run-time errors/undesired behavior.
If you don't need it, don't follow it. The motivation behind the rule of three is that, when you need a destructor, that is usually because you need to do some dynamic deallocations.
If you do deallocations as well, you're going to need the copy constructor and assignment operators as well. Imagine you have a class that has a pointer to something:
struct Foo
{
Foo() { ptr_ = new int; }
~Foo() { delete ptr_; }
int* ptr_;
};
Because you don't define a copy constructor and an assignment operator, whenever you make a copy of a Foo, both the original and the copy will use a pointer to the same int; when either the original or the copy gets destroyed, the pointer is freed, leaving the other with unusable data.
Foo(cont Foo& other) {
other.ptr_ = new int(*ptr_);
}
// Same for operator=
If you don't do any dynamic allocations in your constructor/ destructor, there's a good chance you don't actually need a copy constructor or an assignment operator (but not necessarily).

C++ Assignment Operator without Copy Constructor

The question: Can I define an assignment operator and not the copy constructor? For an internal class (not exposed in the API), is this still a bad design practice?
The reason I need it: As this question mentions, QObject makes its copy constructor and assignment operator private so that if a subclass tries to use either, an error is issued at compile-time.
I need to define an assignment operator however in order to copy the "value" (and not the "identity" as the Qobject documentation describes. I don't use this class's copy constructor anywhere.
The reason I don't want to write a copy constructor is that it will be duplicating code that I won't use anyway.
There's nothing stopping you. It is, however, a pretty dumb idea.
T t = GetSomeT();
versus
T t;
t = GetSomeT();
Pretty trivial to transform the first into the second, but you're just wasting my time, both dev and processor, making me do it. If it's not default-constructible, I guess that it would be harder... but I'm still not seeing the point. The copy constructor can be defined by the compiler if it's trivial, or you can even define it in terms of the assignment operator if you want DRY.
class T {
T(const T& ref) {
*this = ref;
}
};
Not having a copy constructor will also inhibit your ability to copy-and-swap, the usual idiom for implementing assignment operators.
While possible, as DeadMG says, it is rather foolish.
You don't have to call the base class's copy constructor from your own, so if you absolutely have to have value semantics, then it is still possible. But in the context of QObjects, this is still rather unorthodox. Even for your own internal classes, the principle of least surprise still needs to be kept in mind.
If absolutely necessary, I would avoid the traditional copy constructor/assignment operator, and work via member functions. The expected semantics of QObject derivatives will be maintained, but you have a way to explicitely do what you want to have done.
struct SomeType : QObject {
QSharedPointer<SomeType> Clone() const;
//or
SomeType& CopyValue(const SomeType&);
//rest of implementation
};