I am working with writing the big five(copy constructor, copy assignment operator, move constructor, move assignment operator, destructor). And I've hit a bit of a snag with the copy constructor syntax.
Say I have a class foo that has the following private members:
template<class data> // edit
class foo{
private:
int size, cursor; // Size is my array size, and cursor is the index I am currently pointing at
data * dataArray; // edit
}
If I were to write a constructor for this of some arbitrary size X it would look like this.
template<class data> // edit
foo<data>::foo(int X){
size = X;
dataArray = new data[size];
cursor = 0; // points to the first value
}
Now if I wanted to make a copy constructor of another object called bar I'd need to make the following:
template<class data> // edit
foo<data>::foo(foo &bar){
foo = bar; // is this correct?
}
Assuming I have the overloaded = from the code below:
template<class data> // edit
foo<data>::operator=(foo &someObject){
if(this != someObject){
size = someObject.size;
cursor = someObject.cursor;
delete[] dataArray;
dataArray = new data[size];
for(cursor = 0; cursor<size-1;cursor++)
dataArray[cursor] = someObject.dataArray[cursor];
}
else
// does nothing because it is assigned to itself
return *this;
}
Is my copy constructor correct? Or should foo = bar instead be *this = bar ?
I'm still new to templated constructors so if I made any errors in the code please let me know I will correct it.
EDIT 1: Thanks to the answer provided below by Marcin I have made some edits to the code above to make it more syntatically correct and commented them with //edit they are summarized in the list below:
previously template<classname data>, which is incorrect must be template <typename data> or template <class data> for functions and classes respectively.
previously int*dataArray; this missuses the template and should be data* dataArray;
The best way to achieve what you want is to use a class that already handles assignment, copying and moving, taking care of its memory management for you. std::vector does exactly this, and can directly replace your dynamically allocated array and size. Classes that do this are often referred to as RAII classes.
Having said that, and assuming this is an exercise in correctly implementing the various special member functions, I'd suggest that you proceed via the copy and swap idiom. (See What is the copy and swap idiom? on SO, for more details and commentary). The idea is to define the assignment operation in terms of the copy constructor.
Start with the members, constructor and destructor. These define the ownership semantics of the members of your class:
template <class data>
class foo {
public:
foo(const size_t n);
~foo();
private:
size_t size; // array size
size_t cursor; // current index
data* dataArray; // dynamically allocated array
};
template <class data>
foo<data>::foo(const size_t n)
: size(n), cursor(0), dataArray(new data[n])
{}
template <class data>
foo<data>::~foo() {
delete[] dataArray;
}
Here, memory is allocated in the constructor and deallocated in the destructor.
Next, write the copy constructor.
template <class data>
foo<data>::foo(const foo<data>& other)
: size(other.size), cursor(other.cursor), dataArray(new data[other.size]) {
std::copy(other.dataArray, other.dataArray + size, dataArray);
}
(along with the declaration, foo(const foo& other); inside the class body).
Notice how this uses member initialiser lists to set the member variables to the values in the other object. A new allocation is performed, and then in the body of the copy constructor you copy the data from the other object into this object.
Next comes the assignment operator. Your existing implementation has to perform a lot of manipulation of pointers, and isn't exception safe. Let's look at how this could be done more simply and more safely:
template <class data>
foo<data>& foo<data>::operator=(const foo<data>& rhs) {
foo tmp(rhs); // Invoke copy constructor to create temporary foo
// Swap our contents with the contents of the temporary foo:
using std::swap;
swap(size, tmp.size);
swap(cursor, tmp.cursor);
swap(dataArray, tmp.dataArray);
return *this;
}
(along with the declaration in-class, foo& operator=(const foo& rhs);).
[-- Aside: You can avoid writing the first line (explicitly copying the object) by accepting the function argument by value. It's the same thing, and might be more efficient in some cases:
template <class data>
foo<data>& foo<data>::operator=(foo<data> rhs) // Note pass by value!
{
// Swap our contents with the contents of the temporary foo:
using std::swap;
swap(size, rhs.size);
swap(cursor, rhs.cursor);
swap(dataArray, rhs.dataArray);
return *this;
}
However, doing so may cause ambiguous overloads if you also define a move assignment operator. --]
The first thing this does is create a copy of the object being assigned from. This makes use of the copy constructor, so the details of how an object is copied need only be implemented once, in the copy constructor.
Once the copy has been made, we swap our internals with the internals of the copy. At the end of the function body, the tmp copy goes out of scope, and its destructor cleans up the memory. But this isn't the memory that was allocated at the beginning of the function; it's the memory our object used to hold, before we swapped our state with the temporary.
In this way, the details of allocating, copying and deallocating are kept where they belong, in the constructors and the destructor. The assignment operator simply copies and swaps.
This has a further advantage, over and above being simpler: It's exception safe. In the code above, an allocation error could cause an exception to be thrown while creating the temporary. But we haven't modified the state of our class yet, so our state remains consistent (and correct) even when the assignment fails.
Following the same logic, the move operations become trivial. The move constructor must be defined to simply take ownership of the resource and leave the source (the moved-from object) in a well-defined state. That means setting the source's dataArray member to nullptr so that a subsequent delete[] in its destructor doesn't cause problems.
The move assignment operator can be implemented similarly to the copy assignment, although in this case there's less concern with exception safety since you're just stealing the already-allocated memory of the source object. In the complete example code, I opted to simply swap the state.
A complete, compilable-and-runnable example can be seen here.
Your foo class does not internally use data template parameter. I suppose you wanted to use it here:
int * dataArray; // should be: data * dataArray;
You also are not allowed to use classname keyword but typename or class. You have also lots of other compile errors in your code.
Your copy constructor is wrong, it will not compile:
foo = bar; // is this correct? - answer is NO
foo is a class name in this context, so your assumption is correct. *this = someObject this would work (with additional fixes, at least dataArray must be set to nullptr), but your class variables would be default constructed first by copy constructor only to be overwritten by assignment operator, so its quiet non efficent. For more read here:
Calling assignment operator in copy constructor
Is it bad form to call the default assignment operator from the copy constructor?
Related
I am using the pimpl idiom with a const std::unique_ptr to hold the class implementation. My class needs to support copy construction and copy assignement. What I'd like to do is manually call the copy constructor of the impl class inside the unique_ptr. However, I fail to see how.
#include <memory>
struct potato {
potato();
~potato();
potato(const potato& p);
private:
struct impl;
const std::unique_ptr<impl> _pimpl;
};
struct potato::impl {
int carbs = 42;
};
potato::potato()
: _pimpl(std::make_unique<impl>()) {
}
potato::~potato() = default;
potato::potato(const potato& p) {
// Try to call the copy constructor of impl, stored in unique_ptr, not the
// unique_ptr copy-constructor (which doesn't exist).
_pimpl.get()->impl(p._pimpl); // This doesn't work.
}
I've checked out another question about explicitly calling the copy-constructor on an object. One answer recommended using placement new.
Object dstObject;
new(&dstObject) Object(&anotherObject);
Could I use this in my copy-constructor? If so, how? I don't really understand whats happening there. Thank you.
What I'd like to do is manually call the copy constructor of the impl class inside the unique_ptr
Here lies your error. As you are inside the (copy) constructor of potato, there's no impl object already constructed over which you'd have to "manually" invoke the copy constructor.
Just construct your new impl passing to it a reference to the original impl to copy.
potato::potato(const potato& p)
: _pimpl(std::make_unique<impl>(*p._pimpl) {
}
As for assignment, you can easily forward to the impl assignment operator:
potato &operator=(const potato &p) {
*_pimpl = *p._pimpl;
return *this;
}
You can invoke constructors explicitly on uninitialized storage with the placement new operator, as you mentioned. You can return the storage of an object to an uninitialized state by explicitly calling its destructor.
Here’s a simple implementation of the assignment operator that explicitly invokes the copy constructor and the destructor you already defined as part of your interface:
#include <new>
potato& potato::operator=(const potato& x)
{
if ( this != &x ) { // check for self-assignment!
this->~potato();
new(this) potato(x);
}
return *this;
}
You would probably also want to define a move constructor and overload the assignment operator when the right-hand side is a temporary. That is, overload for potato&& src as well as const potato& src. You could use the swap idiom if your class supports it, or the same code as above, but calling new(this) potato(std::move(src));.
If you have access to the destructor and copy constructor of the class wrapped in a smart pointer, you can do the same trick with them, just dereferencing the smart pointers. You probably don’t want to, though.
The default copy constructor and assignment operator ought to work just fine, if the contents of the class are smart pointers, STL containers, and so on. You probably would want to copy the data referenced by the smart pointers by writing things like *p = x or *p = *q or std::swap, rather than explicit calls to the copy constructor.
I am looking at some code that I have inherited and it has a matrix class which implements 2D matrices in C++ and has move constructors and assignment operator.
The way it is implemented is as follows:
template<typename T, int rows, int cols>
class matrix_data {
...
std::unique_ptr<T[]> data_;
// Some definitions
typedef matrix_data<T, rows, cols> this_type
matrix_data(this_type && other)
{
std::swap(data_, other.data_);
}
};
Now, I am not sure why the data pointers are being swapped here. I thought it should be something like
data_ = std::move(other.data_);
I am guessing with the swap it is still ok because the other instance should be in an invalid state anyway after the move.
My question is whether I can replace the statement with data_ = std::move(other.data_); Is there some unique_ptr deletion stuff that is the reason for doing the swap instead of the move i.e. if I do the move would the original data be deleted correctly?
To answer your question:
Yes, you could replace the swapping with
data_ = std::move(other.data_);
but as the comments suggest, that's happening anyway when you do not implement the move constructor, as long as you do not implement neither a copy constructor, copy assignment operator, move assignment operator or destructor. If you have implemented one of the above, marking the move constructor as =default will also do the job.
Swapping the objects' contents is indeed not necessary in this case as there is actually nothing to swap, because this being a (move) constructor, this->data_ does not point to any previously allocated memory location that should be freed after the pointer to it has been overwritten.
Therefore swapping is usually done when implementing the move assignment operator, because in this case this->data_ usually holds a pointer to a memory location that needs to be freed sometime. By putting this pointer into the moved-from object, the memory it is pointing to will be freed when the destructor for the moved-from object is called.
My assignment requires me to create a stack template class. My program is working fine, I was just wondering if its necessary in this case to define the constructor since its only member is a vector. This is the code:
#include<iostream>
#include<vector>
using namespace std;
template <class T>
class Stack{
public:
Stack(){}
void push(const T &item){
data.push_back(item);
}
void pop(){
data.pop_back();
}
bool isEmpty(){
return data.empty();
}
T getTop(){
top = data.back();
return(top);
}
private:
vector<T> data;
T top;
};
If so, would I also need to include a copy constructor? How do I implement either if the only member is a vector?
correction: i also have another member, if you have noticed. Question still stands, though.
If you do not care about initializing top during the construction, then you do can do any of the following three:
Stack(){};
or
Stack(): default;
or not declaring a constructor
However, not declaring is a bad practice and it will create problems if you are using a copy constructor or any other constructor with parameters.
For instance, if you created the constructor:
Stack(T i) { top = i; data.push_back(i); };
without having declared a constructor,
Stack<int>();
would generate a compiler error.
Just make sure that you set the value of top when push function is called (i.e. compare the new element with the current top every time you push, but if data.size() == 1 you should set this as a top without comparing, as top is undefined).
You don't need to declare a default constructor, compiler will generate one for you - unless class T hasn't defined one, on which case you might get an error.
You don't need a copy constructor also, for the same reasons, given the same premises - on this case, class T must have one.
You'll find detailed info on references below.
That been said, I see no reason for the extra "top" member, except for some sort of speed optimization.
References:
Default constructors - cppreference.com
Copy constructors - cppreference.com
First of all, there is no need to define constructor and copy constructor.
If we do not define a constructor and copy constructor, the compiler will synthesizes one, and the synthesized constructor will help us to initialize class member variable. You does not need to initialize any member variable with a special value in your class.
How to define copy control? From C++ Primer: "There are three basic operations to control copies of class objects: the copy constructor, copy-assignment operator, and destructor."
Classes That Need Destructors Need Copy and Assignment: One rule of thumb to use when you decide whether a class needs to define its own versions of the copy-control members is to decide first whether the class needs a destructor. Often, the need for a destructor is more obvious than the need for the copy constructor or assignment operator. If the class needs a destructor, it almost
surely needs a copy constructor and copy-assignment operator as well.
Example:
class Int
{
public:
Int(int vValue = 0) : m_Pointer(new int(vValue)) {}
~Int()
{
delete m_Pointer;
m_Pointer = NULL;
}
private:
int* m_Pointer;
};
We defined an int Wrapper Class like JAVA. This class allocates dynamic memory in its constructor, The synthesized destructor will not delete a data member that is a pointer. Therefore, this class needs to define a destructor to free the memory allocated by its constructor.
Unfortunately, we have introduced a serious bug! This version of the class uses the synthesized versions of copy and assignment. Those functions copy the pointer member, just only copy the address where the pointer member points to:
Int(const Int& vInt)
{
m_Pointer = vInt.m_Pointer;
}
So, you must define your own copy constructor and assignment operator to control the memory assignment.
I understand if you wish to pass a vector of MyClass objects and it is a temporary variable, if there is a move constructor defined for MyClass then this will be called, but what happens if you pass a vector of boost::shared_ptr<MyClass> or std::shared_ptr<MyClass>? Does the shared_ptr have a move constructor which then call's MyClass's move constructor?
if there is a move constructor defined for MyClass then this will be called
Usually not. Moving a vector is usually done my transferring ownership of the managed array, leaving the moved-from vector empty. The objects themselves aren't touched. (I think there may be an exception if the two vectors have incompatible allocators, but that's beyond anything I've ever needed to deal with, so I'm not sure about the details there).
Does the shared_ptr have a move constructor which then call's MyClass's move constructor?
No. Again, it has a move constructor which transfers ownership of the MyClass object to the new pointer, leaving the old pointer empty. The object itself is untouched.
Yes, std::shared_ptr<T> has a move constructor, as well as a templated constructor that can move from related shared pointers, but it does not touch the managed object at all. The newly constructed shared pointer shares ownership of the managed object (if there was one), and the moved-from pointer is disengaged ("null").
Example:
struct Base {}; // N.B.: No need for a virtual destructor
struct Derived : Base {};
auto p = std::make_shared<Derived>();
std::shared_ptr<Base> q = std::move(p);
assert(!p);
If you mean moving std::vector<std::shared_ptr<MyClass>>. Then even the move constructor of std::shared_ptr won't be called. Because the move operation is directly done on std::vectorlevel.
For example, a std::vector<T> may be implemented as a pointer to array of T, and a size member. The move constructor for this can be implemented as:
template <typename T>
class vector {
public:
/* ... other members */
vector(vector &&another): _p(another._p), _size(another._size) {
/* Transfer data ownership */
another._p = nullptr;
another._size = 0;
}
private:
T *_p;
size_t _size;
}
You can see in this process, no data member of type T is touched at all.
EDIT: More specially in C++11 Standard: §23.2.1. General container requirements (4) there is a table contains requirements on implementations of general containers, which contains following requirements:
(X is the type of the elements, u is an identifier declaration, rv is rvalue reference, a is a container of type X)
X u(rv)
X u = rv
C++ Standard: These two (move constructors) should have constant time complexity for all standard containers except std::array.
So it's easy to conclude implementations must use a way like I pointed above for move constructors of std::vector since it cannot invoke move constructors of individual elements or the time complexity will become linear time.
a = rv
C++ Standard: All existing elements of a are either move assigned to or destroyed a shall be equal to the value that rv had before this assignment.
This is for move assign operator. This sentence only states that original elements in a should be "properly handled" (either move-assigned in or destroyed). But this is not a strict requirement. IMHO implementations can choose the best suited way.
I also looked at code in Visual C++ 2013 and this is the snippet I found (vector header, starting from line 836):
/* Directly move, like code above */
void _Assign_rv(_Myt&& _Right, true_type)
{ // move from _Right, stealing its contents
this->_Swap_all((_Myt&)_Right);
this->_Myfirst = _Right._Myfirst;
this->_Mylast = _Right._Mylast;
this->_Myend = _Right._Myend;
_Right._Myfirst = pointer();
_Right._Mylast = pointer();
_Right._Myend = pointer();
}
/* Both move assignment operator and move constructor will call this */
void _Assign_rv(_Myt&& _Right, false_type)
{ // move from _Right, possibly moving its contents
if (get_allocator() == _Right.get_allocator())
_Assign_rv(_STD forward<_Myt>(_Right), true_type());
else
_Construct(_STD make_move_iterator(_Right.begin()),
_STD make_move_iterator(_Right.end()));
}
In this code the operation is clear: if both this and right operand have the same allocator, it will directly steal contents without doing anything on individual elements. But if they haven't, then move operations of individual elements will be called. At this time, other answers apply (for std::shared_ptr stuff).
I was reading C++11 Faq and came across this code. I have a better understanding of C++ coding, but I'm still not able to understand the below code.
template<class T>
class Handle {
T* p;
public:
Handle(T* pp) : p{pp} {}
~Handle() { delete p; } // user-defined destructor: no implicit copy or move
Handle(Handle&& h) :p{h.p} { h.p=nullptr; }; // transfer ownership
Handle& operator=(Handle&& h) { delete p; p=h.p; h.p=nullptr; return *this; } // transfer ownership
Handle(const Handle&) = delete; // no copy
Handle& operator=(const Handle&) = delete;
// ...
};
What does "transfer ownership" mean?
Why is the copy ctor equated to "delete"? how is it useful?
Please if someone can add a few examples with explanation, it would be a great help.
It's a move constructor, the special && syntax introduced in C++11 takes a rvalue reference, so a reference to a variable which has no name and can't be referenced anywhere else inside the code.
What happens in the constructor is that the Handle takes the ownership of the Handle passed through the move constructor in the way that it steals (pass me the term) the T* p inside by assigning its value to its own variable and then setting nullptr to the variable of the rvalue passed.
This is used because you don't really need to copy an rvalue, since that value won't be used anymore in the code, so it's safe to just take its data, this avoids a, possibly costly, copy constructor.
In C++ you had copy constructors and copy operators, which were expensive if your object was big. Now in C++11 you have move constructor and move operator which says "take everything from the source and kill it".
mybigthing y ;
...
mybigthing x( move(y)) ;
y is created with lots of stuff internally. after x(y), y is now empty and all the big stuff is in x.
One of the main reasons for this is to make returning big objects from functions free:
mybigthing f()
{
mybigthing tmp ;
...
return tmp ;
}
{
mybigthing y= f() ;
}
In c++03, this would be horrible performance wise. Now its free. The compilers are required to actually use y as the temporary inside of f() and never do any copies.
transfer ownership means if you do a=b the contents of b belong to a and does not exist in b anymore. This makes more sense in the example {A a; dosomething(a); return a;}. a exist locally in the function. It's contents are being moved into the return value. If A is a typedef for std::string it would mean the string internals have been moved instead of making a copy of a intentionally long string (html page maybe). However I believe string has a copy on write flag so it wouldn't make a copy in that situation but other classes may not bother to implement a copy on write.
The reason the constructor and assignment operator (which are move, not copy) delete is because the current p may be pointing to something. Not freeing it means a memory leak.
about your second question:
Why is the copy ctor equated to "delete"? how is it useful?
Here is an answer:
http://www.developerfusion.com/article/133063/constructors-in-c11/
C++11 Explicitly Deleted Constructors
C++11 also supports the concept of explicitly deleted constructors.
For example, you can define a class for which you do not want to write
any constructors and you also do not want the compiler to generate the
default constructor. In that case you need to explicitly delete the
default constructor:
class MyClass { public:
MyClass() = delete; };