Examples of empty and deleted copy constructors:
class A
{
public:
// empty copy constructor
A(const A &) {}
}
class B
{
public:
// deleted copy constructor
A(const A&) = delete;
}
Are they doing the same in practice (disables copying for object)? Why delete is better than {}?
Are they doing the same in practice (disables copying for object)?
No. Attempting to call a deleted function results in a compile-time error. An empty copy constructor can be called just fine, it just default-initializes the class members instead of doing any copying.
Why delete is better than {}?
Because you're highly unlikely to actually want the weird "copy" semantics an empty copy constructor would provide.
One reason is syntactic sugar -- no longer need to declare the copy constructor without any implementation. The other: you cannot use deleted copy constructor as long as compiler is prohibited from creating one and thus first you need to derive new class from that parent and provide the copy constructor. It is useful to force the class user to create own implementation of it including copy constructor for specific library class. Before C++ 11 we only had pure virtual functions with similar intent and the constructor cannot be virtual by definition.
The default or existing empty copy constructor does not prevent an incorrect use of the class. Sometimes it is worth to enforce the policy with the language feature like that.
Empty Copy constructor is used for default initializing the member of class.
While delete is use for prevent the use of constructor.
Related
The title pretty much sums up my question. In more detail: I know that when I declare a move constructor and a move assignment operator in C++11 I have to "make the other objects variables zero". But how does that work, when my variable is not an array or a simple int or double value, but its a more "complex" type?
In this example I have a Shoplist class with a vector member variable. Do I have to invoke the destructor of the vector class in the move assignment operator and constructor? Or what?
class Shoplist {
public:
Shoplist() :slist(0) {};
Shoplist(const Shoplist& other) :slist(other.slist) {};
Shoplist(Shoplist&& other) :slist(0) {
slist = other.slist;
other.slist.~vector();
}
Shoplist& operator=(const Shoplist& other);
Shoplist& operator=(Shoplist&& other);
~Shoplist() {};
private:
vector<Item> slist;
};
Shoplist& Shoplist::operator=(const Shoplist& other)
{
slist = other.slist;
return *this;
}
Shoplist& Shoplist::operator=(Shoplist&& other)
{
slist = other.slist;
other.slist.~vector();
return *this;
}
Whatever a std::vector needs to do in order to move correctly, will be handled by its own move constructor.
So, assuming you want to move the member, just use that directly:
Shoplist(Shoplist&& other)
: slist(std::move(other.slist))
{}
and
Shoplist& Shoplist::operator=(Shoplist&& other)
{
slist = std::move(other.slist);
return *this;
}
In this case, you could as AndyG points out, just use = default to have the compiler generate exactly the same move ctor and move assignment operator for you.
Note that explicitly destroying the original as you did is definitely absolutely wrong. The other member will be destroyed again when other goes out of scope.
Edit: I did say assuming you want to move the member, because in some cases you might not.
Generally you want to move data members like this if they're logically part of the class, and much cheaper to move than copy. While std::vector is definitely cheaper to move than to copy, if it holds some transient cache or temporary value that isn't logically part of the object's identity or value, you might reasonably choose to discard it.
Implementing copy/move/destructor operations doesn't make sense unless your class is managing a resource. By managing a resource I mean be directly responsible for it's lifetime: explicit creation and destruction. The rule of 0 and The rule of 3/5 stem from this simple ideea.
You might say that your class is managing the slist, but that would be wrong in this context: the std::vector class is directly (and correctly) managing the resources associated with it. If you let our class have implicit cpy/mv ctos/assignment and dtors, they will correctly invoke the corresponding std::vector operations. So you absolutely don't need to explicitly define them. In your case the rule of 0 applies.
I know that when I declare a move constructor and a move assignment
operator in C++11 I have to "make the other objects variables zero"
Well no, not really. The ideea is that when you move from an object (read: move it's resource from an object) then you have to make sure that your object it's left aware that the resource it had is no more under it's ownership (so that, for instance, it doesn't try to release it in it's destructor). In the case of std::vector, it's move ctor would set the pointer it has to the internal buffer to nullptr.
I know that when I declare a move constructor and a move assignment operator in C++11 I have to "make the other objects variables zero"
This is not quite correct. What you must do, is maintain validity of the moved from object. This means that you must satisfy the class invariant.
If you have specified a special invariant for a particular class, that requires you to set member variables to zero, then perhaps such class might have to do so. But this is not a requirement for move in general.
Do I have to invoke the destructor of the vector class in the move assignment operator and constructor?
Definitely not. The destructors of the members will be called when the moved from object is destroyed.
What you would typically do, is move construct/assign each member in the move constructor/assignment operator of the containing object. This is what the implicitly generated special member functions do. Of course, this might not satisfy the class invariant for all classes, and if it doesn't, then you may need to write your own versions of them.
The compiler will implicitly generate the special member functions for you, if you don't try to declare them yourself. Here is a minimal, but correct version of your class:
class Shoplist {
vector<Item> slist;
};
This class is default constructible, movable and copyable.
The move constructor should move member-wise:
Shoplist(Shoplist&& other)
: slist(std::move(other.slist))
{}
Note, that the compiler generates move constructors for you (when possible) by member-wise move, as you would do by hand above.
Move constructors are allowed (but not required) "steal" the contents of the moved-from object. This does not mean that they must "make the other objects variables zero". Moving a primitive type, for instance, is equivalent to copying it. What it does mean is that a move constructor can transfer ownership of data in the heap or free store. In this case, the moved-from object must be modified so that when it is destroyed (which should not happen in the move-constructor), the data it previously owned (before it was transferred) will not be freed.
Vector provides its own move constructor. So all you need to do in order to write a correct move constructor for an object containing a vector is to ensure the correct vector constructor is invoked. This is done by explicitly passing an r-value reference to the sub-object constructor, using std::move:
Shoplist(Shoplist&& other) :slist(std::move(other.slist)) {
//... Constructor body
... But in fact you probably don't need to do this in general. Your copy and move constructors will be correctly auto-generated if you don't declare them and don't declare a destructor. (Following this practice is called the "rule of 0".)
Alternatively, you can force the compiler to auto-generate the move constructor:
Shoplist(Shoplist&& other) = default;
I'm trying to initialize one object into other object using copy constructor. I'm puzzled that if I comment out copy constructor it initializes fine but with following code it does not.
class TDateTime : public TData {
public:
TDateTime() : TData(EDataStateInvalid) {}
TDateTime(const tm& aTm){};
TDateTime(int aTm_sec, int aTm_min, int aTm_hour,
int aTm_mday, int aTm_mon, int aTm_year, int aTm_wday,int aTm_isdst){
value.tm_sec=aTm_sec;
value.tm_min=aTm_min;
value.tm_hour=aTm_hour;
value.tm_mday=aTm_mday;
value.tm_mon=aTm_mon;
value.tm_year=aTm_year;
value.tm_wday=aTm_wday;
value.tm_isdst=aTm_isdst;
};
virtual ~TDateTime() {cout<<"Destroying TDateTime ";};
//! Copy constructor
TDateTime(const TDateTime& aInstance){};
//! Copies an instance
virtual const TDateTime& operator=(const TDateTime& aInstance){return *this;};
private:
tm value;
};
main.cpp
tm=createDateTime(x);
TDateTime aDateTimeFrom(tm.tm_sec,tm.tm_min,tm.tm_hour,tm.tm_mday,tm.tm_mon,tm.tm_year,tm. tm_wday,0);
TDateTime aDateTimeTo(aDateTimeFrom);
if I comment out the copy constructor it copies fine. If I remove {} then compiler complains about undefined symbol.
Can you suggest what is wrong here?
Based on answer about empty copy constructor does nothing, I comment it out and copy is perfect but I have another problem. If I do
TDateTime aDateTime;
aDateTime=aDateTimeFrom;
aDateTime has all junk values. Any pointers on this?
//! Copy constructor
TDateTime(const TDateTime& aInstance){};
Your copy constructor does nothing. There is no magic involved with user-written copy constructors; if you don't make them do anything, then they will not do anything.
More precisely, a new instance is created, but its members are left uninitialised or are default-initialised.
While we're at it...
//! Copies an instance
virtual const TDateTime& operator=(const TDateTime& aInstance){return *this;};
Same problem here. Your copy-assignment operator does not do anything.
By convention, it should also not return a const reference but a non-const one.
It may be worth the mention that your intution seems to be correct, as your goal should indeed be to create classes which don't require any self-written copy constructors or copy-assignment operators because all members know how to correctly copy or copy-assign themselves (like std::string or std::vector or std::shared_ptr). But in that case, rather than defining the member functions with empty implementations, you just don't declare them at all in your code, such that the compiler can handle everything automatically.
And finally, one other thing: A good rule of thumb for C++ classes is that they should either have virtual functions and disable copying (sometimes called "identity classes") or have no virtual functions and allow copying (sometimes called "value classes"). Something like a virtual assignment operator often indicates an overly complicated, hard-to-use and error-prone class design.
A compiler generates a copy constructor which performs member-wise copy if the user hasn't declared a copy constructor. If the user does declare a copy-constructor, then the copy constructor does what the user has told it to, in your case - exactly nothing.
TDateTime(const TDateTime& aInstance){ /* empty body*/};
Your define a copy constructor which does not do anything.
In your case you don't really need a copy constructor and/or copy assignment operator, the compiler generated versions would be enough (it would be wise to make sure/recheck that tm class can handle the copying).
There is a rule of three, which states that one needs copy constructor and copy assignment operator if one defines a destructor. But it is only a rule of thumb and not an actual necessity. In your case there is no memory management involved and you use the destructor only for logging.
So do not declare a copy constructor at all (your assign operator has the same flaw by the way - it does not copy anything) and let the compiler do the work.
I am new to object oriented programming, and this may be a silly question, but I don't understand why is using class A code better to use than class B if you want to create copy of one object.
class A {
int num;
public:
A(const A &ref) : num(ref.num) {};
};
class B {
int num;
public:
B(B *ptToClass) : num(ptToClass->num) {};
};
If I got this right, copy constructor is used in class A.
If you don't declare a copy constructor for your class, the compiler will declare one for you anyway. Classes have to have copy constructors. They're baked into the language and have special status. The language doesn't work without them.
Possibly the best example is that copy constructors are needed when passing by value. The compiler is going to implicitly call the copy constructor when you pass by value. It's not going to call the constructor B::B(B*).
So if you want your class to be copyable, you should define the copying logic in the copy constructor. It's just easier.
Class A is flexible and safe: you create a copy from any A object you have, even if it's a temporary one.
Class B is less safe as you could invoke the constructor with a nullptr. It's less flexible because you can only use ypur constructor to copy an object from which you can get the address and which is not const.
B b1(...);
const B b2(...);
B fb(); // function returning a B
B b3(&b1);
B b4(&b2); // error b2 is const
B b5(&fb()); // error you can't take adress of a temporary
The thing is that if a constructor is considered to be a copy constructor by the compiler, it is used in special ways. For instance, if you have a function that takes a parameter of your type A by copy, like this:
void function(A obj) {
// Do something with A
// ...
}
And then you call that function:
int main() {
A a_obj;
function(a_obj);
}
the object obj received by function will be created by the copy constructor you provided. So, it is a nice thing to provide copy constructor for your classes that are meant to be copied, so that them fits more nicely with the languages features and libraries.
There is no problem in creating a constructor of the kind in your class B, if that fit your needs in your application, but that will not be understood by the compiler as a copy constructor, and won't be used when the compiler or libraries needs to copy your objects.
It is forbidden by standard to use pointers in copy constructors:
C++ draft standard n3376 - section 12.8.2:
A non-template constructor for class X is a copy constructor if its
first parameter is of type X&, const X&, volatile X& or const volatile
X&, and either there are no other parameters or else all other
parameters have default arguments
Why is the argument of the copy constructor a reference rather than a pointer?
I think a more appropriate question to ask is: when to provide a user-defined copy constructor over the default one provided by the compiler?
As we know, the compiler provides a copy constructor (the default one) which does a memberwise copy.
This memberwise copy is not bad as long as the class is a simple concrete type (that behaves for the most part like a built-in type). But for complex concrete types or classes with hierarchies, memberwise copy is not a good idea, and the programmer is highly advised to provide his own implementation of the copy constructor (that is, provide user-defined copy constructor).
As a thumb rule, it is a good idea to provide user-defined copy constructor in the class.
is that correct to write a constructor like this?
class A
{
A(const A& a)
{
....
}
};
if yes, then is it correct to invoke it like this:
A* other;
...
A* instance = new A(*(other));
if not, what do you suggest?
Thanks
Almost correct. When declaring the constructor in the class, simply write A, not A::A; you would use A::A when giving a definition for the constructor outside of the class declaration. Otherwise, yes.
Also, as James points out, unless you are copying from an object that you are accessing via a pointer, you don't need to do any dereferencing (if it is a value or a reference). One typically does not use pointers unless it is necessary to do so. On that principle, you would have something like:
A x; // Invoke default constructor
// ...
// do some thing that modify x's state
// ...
A cpy(x); // Invokes copy constructor
// cpy now is a copy of x.
Note, though, that the first statement A x invokes the default constructor. C++ will provide a default implementation of that constructor, but it might not be what you want and even if it is what you want, it is better style, IMHO, to give one explicitly to let other programmers know that you've thought about it.
Edit
C++ will automatically provide an implementation of the default constructor, but only if you don't provide any user-defined constructors -- once you provide a constructor of your own, the compiler won't automatically generate the default constructor. Truth be told, I forgot about this as I've been in the habit of giving all constructor definitions myself, even when they aren't strictly necessary. In C++0x, it will be possible to use = default, which will provide the simplicity of using the compiler-generated constructor while at the same time making the intention to use it clear to other developers.
No, you are writing a copy constructor. It will not act as you expect (according to the examples provided).
class A{
A(arguments){ ...}
}
I would suggest reading a C++ book, differences between a constructor and a copy constructor are well explained.
When is it used ? When an instance is copied. For example, by returning /passing an instance by value
void foo (A a){
//copy constructor will be called to create a
}
A bar(){
return a; //Copy constructor will be called
}
In writing a copy constructor for one of my classes ( which holds a few objects of other UDTs ), I am required to create a default constructor for those UDTs, even though they were never really meant to have one.
Is it fine to just implement a blank default constructor and be done with it? The only time the default constructor is invoked is during this copying, when the object is created and then the values of the corresponding object are copied to it. Thus, whatever values are assigned to the object in the default constructor will never actually be used.
The problem I see is that some member variables aren't initialized in a blank default constructor. Should I just write one that gives dummy values instead? Any other recommended ways to handle this?
Edit: I understand that a copy constructor doesn't NEED a default constructor if I were to define copy constructors for the other classes, but I didn't, so it does need it.
If you use an initializer list in the copy constructor, you don't need a default constructor:
#include <iostream>
using namespace std;
class Foo {
Foo(); /* no default constructor */
public:
Foo(int i) { cout << "Foo constructor (int)" << endl; }
Foo(const Foo& f) { cout << "Foo constructor (copy)" << endl; }
};
class Bar {
Foo f;
public:
Bar() : f(1) { cout << "Bar constructor (default)" << endl; }
Bar(const Bar& b) : f(b.f) { cout << "Bar constructor (copy)" << endl; }
};
int main(void) {
Bar b;
Bar b_=b;
return 0;
}
Results in:
Foo constructor (int)
Bar constructor (default)
Foo constructor (copy)
Bar constructor (copy)
Are you actually sure you need a copy constructor? It's unusual (but not impossible) to have a class where the default constructor would be OK, but you need a custom copy constructor. Perhaps you could post the code for your class?
It sounds to me like you need to define copy c'tors for the other classes, as you are creating objects of them by copying other objects.
You say:
when the object is created and then
the values of the corresponding object
are copied to it.
But ask yourself - how do the values of that "corresponding object" get there in the first place. I.e. how was the corresponding object created?
This previous SO discussion may help clarify matters for you.
This doesn't sound like the best way to implement a copy constructor. If the contained types provide copy constructors themselves - use those. There might be a reason a type does not provide a default constructor after all.
I would first ask why copying those UDTs involves the default constructor, rather than the more appropriate copy constructor. I would also ask what it means for an object to be in the default initialized state — if it does mean something, then by all means implement it.
If you have no reasonable meaning for a default initialization, and you absolutely have to define the object using a default constructor, I suppose implementing a default constructor could be afforded.
However, not all objects can get a default constructor, so fixing the source of the problem is still a good idea.
You can prevent the default constructor by requiring the other object to have copy constructors also (Or use special constructor which pass in all information needed to construct the objects. Generally having default constructor which don't initialize all member variables is a very bad idea. At a minimum make sure the default constructors of the other class initializes all members.
If you don't want the compiler to generate a copy constructor or don't want a copy constructor at all, then declare a private copy constructor but don't provide any definition (code) for it. The compiler will see the declarations and not generate one. Also do this with the assignment operator.
I do this with my singleton classes.
If your class isnt meant to be defaultly constructed, don't create a default constructor.
If it is, then I'm sure you can figure out a sensible initialization, so that's what you should be using.
Remember a thumb rule that as far as something is not part of specification , compiler won't do it for you.
If your class contain user defined type and when you create object of it , then compiler has to call default constuctor for each object.
But to initialize data members of object is not complier's task, but you are suppose to do it.
For the case you have mentioned , you need your own custom copy constructor and assignment operator.
The question, the way you stated it, appears to make no sense. Copy-constructor does not need the default constructor, as you seem to believe. Copy-constructor is a completely independent full-fledged constructor that construct an object completely by itself.
If you construct your objects with copy-constructor, then you don't need a default one. If you construct your objects with default constructor, then you can't use the copy-constructor on them. It is not possible to "apply" two different constructors to the same object.
If you construct your objects in both ways, then they become two completely independent constructors, each having its own independent purpose. In this case the question you should be asking yourself is how you want your objects to be defualt-constructed. Only you know that.
Again, you need to clarify your question. I would suspect (from your description) that maybe what you are trying to implement is not copy-constructor, but a copy-assignment operator. But that's just a wild guess.