I have a class
class MyClass
{
public :
int a;
int b;
}
For using the copy-swap idiom I then create the function
void MyClass::swap(MyClass& other)
{
std::swap(a,other.a);
std::swap(b,other.b);
}
If, later, I change my class and remove the member a, then the compiler will complain in the swap function, and that's fine.
But if I add a new member, my swap function is not correct anymore. What can I do in order to not forget adding the new member to the swap function ?
The problem is that your answer is not the copy and swap idiom. The actual copy and swap idiom is to write the copy constructor, and move operations for the class. The latter will give you an efficient swap operation via std::swap. Then you write your copy assignment by calling your class copy constructor to create a local copy. Then swap *this with the temporary. You don't do it member by member.
The best way to not forget is to just not write any of the special member functions, and have the compiler generate them for you. This is called the rule of zero. Most classes should not need to write these methods but simply choose members (or write them) such that the generated ones are correct. One of the reasons being no extra maintenance when adding a member.
Finally, if you are writing a resource management class and are writing these functions by hand, you don't necessarily want to use copy and swap. Copy and swap basically trades performance for strong exception safety. I've almost never made use of strong exception safety and in many domains it's just not practical to write things this way. So only use it if you need it.
Related
For example, I want to declare a class but I want the client to not be able to use the copy constructor (or copy assignment operator)
Both of the following two does not allow the use of the copy constructor:
1.
class Track
{
public:
Track(){};
~Track(){};
private:
Track(const Track&){};
};
2.
class Track
{
public:
Track(){};
~Track(){};
Track(const Track&)=delete;
};
Is one of these ways "more correct" than the other or are equal? Is there any side-effect?
//Does not compile with both the above ways
int main()
{
Track l;
Track p(l);
}
Making it private is the "old" way of doing it. The constructor still exists, but it is private, and can only be invoked from within another class member function.
= delete deletes the constructor. It is not generated by the compiler, and it simply will not exist.
So most likely, = delete is what you want. (although with the caveat that not all compilers support this syntax yet, so if portability is a concern...)
Declaring a copy constructor private still allows member functions of the Track class to copy-construct instances of that class, while making it deleted simply forbids copy-constructing that object.
In C++11, deleting a copy constructor is the right way to express the fact that a class is non-copyable (unless of course it makes sense for you to let member functions of Track, or friends of Track, to copy-construct Track objects).
Making a constructor private was basically a "hack" in the old C++, since it was the only way to prevent users from using them. The ability to delete special member functions was only introduced in C++11, and it's the better and more idiomatic way to say that a class cannot be copied. since it is explicit about the intention.
Private constructors have other uses other than forbidding their use entirely (e.g. they may be called by static class member functions). So just making a constructor private doesn't communicate the intention very well, and the resulting error is not very clear, either.
Your first solution conveys to the reader that the copy-constructor is private and is not to be used.
Your second solution is only valid in C++11. Because of this, I'd say the more portable and readable implementation would be your first, using the private-property.
In the first case, you are essentially declaring a private copy constructor and then not providing any implementation. By declaring them private, non-members cannot copy it.
In the second case, the syntax forbids a copy being made. This is C++ native.
The major difference as a programmer is readability and understanding the code. The first case is redundant, why declare the copy constructor, make it private, and not implement it. The client has to infer a lot here.
You can just use "= delete" and clearly imply what you're trying to do.
Your first approach doesn't prevent the class itself from copying itself. The traditional way to solve this is to declare the copy-constructor private and to leave it unimplemented.
An issue with that, however, is that the intent might not be obvious. Someone reading the code might not understand why an orphaned declaration exists and might mistakenly remove it. Comments can help, as would privately inheriting from boost::noncopyable if Boost is available to you.
The second approach makes the intent obvious and is what you should prefer if you can use C++11.
If you are on C++11, use delete. The reason is that it makes the call explicit and the intent clear. You could still accidentally use a private constructor (e.g. in a restricted set of scopes), but the compiler will forbid you from ever using a deleted constructor.
One issue of the private constructor is that the class and friends can still use it -- this results not in access errors but link errors, which can be hard to trace back to the callsite.
If your necessary toolchains do not support deleted constructors (= delete), you should not define it (as seen in your question) -- only declare it and leave it undefined, e.g.: private: \n Track(const Track&);
I've written a simple linked list because a recent interview programming challenge showed me how rusty my C++ has gotten. On my list I declared a private copy constructor because I wanted to explicitly avoid making any copies (and of course, laziness). I ran in to some trouble when I wanted to return an object by value that owns one of my lists.
class Foo
{
MyList<int> list; // MyList has private copy constructor
public:
Foo() {};
};
class Bar
{
public:
Bar() {};
Foo getFoo()
{
return Foo();
}
};
I get a compiler error saying that MyList has a private copy constructor when I try to return a Foo object by value. Should Return-Value-Optimization negate the need for any copying? Am I required to write a copy constructor? I'd never heard of move constructors until I started looking for solutions to this problem, is that the best solution? If so, I'll have to read up on them. If not, what is the preferred way to solve this problem?
The standard explicitly states that the constructor still needs to be accessible, even if it is optimized away. See 12.8/32 in a recent draft.
I prefer making an object movable and non-copyable in such situations. It makes ownership very clear and explicit.
Otherwise, your users can always use a shared_ptr. Hiding shared ownership is at best a questionable idea (unless you can guarantee all your values are immutable).
The basic problem is that return by value might copy. The C++ implementation is not required by the standard to apply copy-elision where it does apply. That's why the object still has to be copyable: so that the implementation's decision when to use it doesn't affect whether the code is well-formed.
Anyway, it doesn't necessarily apply to every copy that the user might like it to. For example there is no elision of copy assignment.
I think your options are:
implement a proper copy. If someone ends up with a slow program due to copying it then their profiler will tell them, you don't have to make it your job to stop them if you don't want to.
implement a proper move, but no copy (C++11 only).
change getFoo to take a Foo& (or maybe Foo*) parameter, and avoid a copy by somehow mutating their object. An efficient swap would come in handy for that. This is fairly pointless if getFoo really returns a default-constructed Foo as in your example, since the caller needs to construct a Foo before they call getFoo.
return a dynamically-allocated Foo wrapped in a smart pointer: either auto_ptr or unique_ptr. Functions defined to create an object and transfer sole ownership to their caller should not return shared_ptr since it has no release() function.
provide a copy constructor but make it blow up somehow (fail to link, abort, throw an exception) if it's ever used. The problems with this are (1) it's doomed to fail but the compiler says nothing, (2) you're enforcing quality of implementation, so your class doesn't work if someone deliberately disables RVO for whatever reason.
I may have missed some.
The solution would be implementing your own copy constructor that would use other methods of MyList to implement the copy semantics.
... I wanted to explicitly avoid making any copies
You have to choose. Either you can't make copies of an object, like std::istream; then you have to hold such objects in pointers/references, since these can be copied (in C++11, you can use move semantics instead). Or you implement the copy constructor, which is probably easier then solving problems on each place a copy is needed.
Are there some drawbacks of such implementation of copy-constructor?
Foo::Foo(const Foo& i_foo)
{
*this = i_foo;
}
As I remember, it was recommend in some book to call copy constructor from assignment operator and use well-known swap trick, but I don't remember, why...
Yes, that's a bad idea. All member variables of user-defined types will be initialized first, and then immediately overwritten.
That swap trick is this:
Foo& operator=(Foo rhs) // note the copying
{
rhs.swap(*this); //swap our internals with the copy of rhs
return *this;
} // rhs, now containing our old internals, will be deleted
There are both potential drawbacks and potential gains from calling operator=() in your constructor.
Drawbacks:
Your constructor will initialize all the member variables whether you specify values or not, and then operator= will initialize them again. This increases execution complexity. You will need to make smart decisions about when this will create unacceptable behavior in your code.
Your constructor and operator= become tightly coupled. Everything you need to do when instantiating your object will also be done when copying your object. Again, you have to be smart about determining if this is a problem.
Gains:
The codebase becomes less complex and easier to maintain. Once again, be smart about evaluating this gain. If you have a struct with 2 string members, it's probably not worth it. On the other hand if you have a class with 50 data members (you probably shouldn't but that's a story for another post) or data members that have a complex relationship to one another, there could be a lot of benefit by having just one init function instead of two or more.
You're looking for Scott Meyers' Effective C++, Item 12: "Copy all parts of an object", whose summary states:
Copying functions should be sure to copy all of an object's data members and all of its base class parts.
Don't try to implement one of the copying functions in terms of the other. Instead, put common functionality in a third function that both
call.
If I change it to void setOutputFormat(ostream& out, int decimal_places),
with a call by reference, it works. I don't understand why though?
What is the difference between a struct and a class, besides struct members are by default public, and class members are by default private?
You're right that there is no difference between class and struct, except the default private vs private.
The problem here is that ostream doesn't have a copy constructor, so you can't pass it by value.
When you attempt to pass the ostream by value, you attempt to make a copy of the stream, which is not valid because stream objects are noncopyable, that is, they do not define a copy constructor. When you pass the stream by reference, however, the function receives a modifiable alias to the ostream instance. Take for instance:
void increment(int n) {
// Increment local copy of value.
++n;
}
int x = 5;
increment(x);
// x is still 5.
Versus:
void increment(int& n) {
// Increment value itself.
++n;
}
int x = 5;
increment(x);
// x is now 6.
So passing the stream by reference is the only way that makes sense, since you want setOutputFormat to modify the original stream in-place. Hope this clarifies the issue somewhat.
As other said, you're trying to create a copy of a noncopyable object (the stream), which results in that error.
In C++ when you pass a var as a parameter, you make a copy of it (opposed to C#, where, for reference types, you're always implicitly passing a reference to it).
By default C++ provides a bitwise copy constructor for every class, but often it's not what is required: think, for example, to a class that owns a resource handle: if you make a perfect clone of an object of that type you'll have two class who think to own such resource, and both will try to destroy it at their destruction, which clearly isn't nice.
Because of this, C++ lets you provide a copy constructor for each class, which is called when a copy of an object has to be created. Since for many objects (streams included) creating copies isn't desired (because it makes no sense, because it's not convenient or because the trouble isn't worth the work) often the copy constructor is disabled (by marking it as private or protected), and you can't create copies of such objects.
Moreover, in general you must be careful with assignments and copies by value with object belonging to complicated class hierarchies, because you may incur in object slicing and other subtle problems. Actually, it's common practice to block copy and assignment in classes intended to be base classes.
The solution, in most cases (including yours) is to pass such objects by reference, thus avoiding making copies at all; see #Jon Purdy's answer for an example.
By the way, often even with copyable objects (e.g. std::strings) it's better to just pass references, to avoid all the work associated with copying; if you're passing a reference just for the sake of efficiency but you don't want to have your object modified, the best solution usually is a const reference.
Copies are also used in some other places in C++; I advise you to have a look at wikipedia page about copy constructors to understand a bit better what's going on, but, over all, to grab a C++ book and read it: C# is different from C++ in a lot of ways, and there are many fake-similarities that may confuse you.
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 10 years ago.
Say I've got a class where the sole data member is something like std::string or std::vector. Do I need to provide a Copy Constructor, Destructor and Assignment Operator?
In case your class contains only vector/string objects as its data members, you don't need to implement these. The C++ STL classes (like vector, string) have their own copy ctor, overloaded assignment operator and destructor.
But in case if your class allocates memory dynamically in the constructor then a naive shallow copy will lead to trouble. In that case you'll have to implement copy ctor, overloaded assignment operator and destructor.
The usual rule of thumb says: if you need one of them, then you need them all.
Not all classes need them, though. If you class holds no resources (memory, most notably), you'll be fine without them. For example, a class with a single string or vector constituent doesn't really need them - unless you need some special copying behavior (the default will just copy over the members).
The default copy constructor will copy the vector if it is declared by value. Beware if you stored pointers in your vector, in such a case, you need to provide specific behaviour for copy/assignement/destruction to avoid memory leaks or multiple delete.
I can think of a few cases when you need to write your own Big Three. All standard containers know how to copy and destroy themselves, so you don't necessarily need to write them. Here's how to know when you do:
Does my class own any resources?
The default copy semantics for pointers is to copy the value of the pointer, not what it points to. If you need to deep copy something, even if it's stored inside a standard container, you need to write your own copy constructor and assignment operator. You also need to write your own destructor to properly free those resources.
Might someone inherit from my class?
Base classes need a destructor. Herb Sutter recommends making them either public and virtual (most common case) or protected and non-virtual, depending on what you want to do with them. The compiler-generated destructor is public and non-virtual, so you'll have to write your own, even if it doesn't have any code in it. (Note: this doesn't imply you have to write a copy constructor or assignment operator.)
Should I prevent a user from copying objects of my class?
If you don't want the user to copy your objects (maybe that's too expensive), you need to declare the copy constructor and assignment operators either protected or private. You don't have to implement them unless you need them. (Note: this doesn't imply you have to write a destructor.)
Bottom line:
The most important thing is to understand what the compiler-generated copy constructor, assignment operator, and destructor will do. You don't need to be afraid of them, but you need to think about them and decide if their behavior is appropriate for your class.
No but there are a number of reasons why you shouldn't allow the compiler to auto generate these functions.
In my experience it is always best to define them yourself, and to get into the habit of making sure that they are maintained when you change the class. Firstly you may well want to put a breakpoint on when a particular ctor or dtor is called. Also not defining them can result in code bloat as the compiler will generate inline calls to member ctor and dtor (Scott Meyers has a section on this).
Also you sometimes want to disallow the default copy ctors and assignments. For example I have an application that stores and manipulates very large blocks of data. We routinely have the equivalent of an STL vector holding millions of 3D points and it would be a disaster if we allowed those containers to be copy constructed. So the ctor and assignment operators are declared private and not defined. That way if anyone writes
class myClass {
void doSomething(const bigDataContainer data); // not should be passed by reference
}
then they'll get a compiler error. Our experience is that an explicit become() or clone() method is far less error prone.
So all in all there are many reason to avoid auto generated compiler functions.
those container will need a "copy constructible" element, and if you don't supply the copy constructor, it will call default copy constructor of your class by deducing from your class members (shallow copy).
easy explanation about default copy constructor is here : http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html
it is so with destructor, the container need to have access to your destructor or your default class destructor if you don't provides one (ie. it will not work if you declare your destructor as private )
you need to provide them if you need them. or possible users of your classes. destructor is always a must, and copy constructors and assignment operator are automatically created by compiler. (MSVC at least)
When ever you have a class that requires deep copies, you should define them.
Specifically, any class which contains pointers or references should contain them such as:
class foo {
private:
int a,b;
bar *c;
}
Subjectively, I would say always define them, as the default behavior provided by the compiler generated version may not be what you expect / want.
Not for strings or vectors, since the trivial constructors / destructors etc, will do fine.
If your class has pointers to other data and need deep copies, or if your class holds a resource that has to be deallocated or has to be copied in a special way.