I am writting a small wrapper around a library that uses handles.
Basic uses of this library are :
int handle;
createHandle( 1, &handle )
doSomethingWithHandle( handle );
// ...
destroyHandle( handle );
I made a wrapper class following RAII principles:
Handle::Handle()
{
createHandle( 1, &m_handle );
}
Handle::~Handle()
{
if( m_handle!= 0 )
destroyHandle( m_handle );
}
Handle::Handle( Handle&& h ) :
m_handle( h.m_handle )
{
h.m_handle = 0;
}
Handle& Handle::operator=( Handle&& h )
{
m_handle = h.m_handle;
h.m_handle = 0;
return *this;
}
// copy constructor and copy assignment operator are explicitely deleted
It's working, however, a lot a classes depends on those wrappers, which means everytime a class has a Handle member, I have to explicitely write move constructor/move assignment operators:
SomeClass::SomeClass( SomeClass&& s ) :
m_handle( std::move( s.m_handle ) )
{
}
SomeClass& SomeClass::SomeClass( SomeClass&& s )
{
m_handle = std::move( s.m_handle );
return *this;
}
This is, of course, not hard to do, but I wonder if there is a way to avoid that, because thats a lot of redundant code.
If that's not possible, why aren't the move operators not generated by the compiler? Let's take the following lines:
SomeClass a;
m_vector.push_back( a );
In this case, someclass is not copyable so the compiler will have an error because a.m_handle have copy operators deleted. So it means we HAVE to move them. But if we do, doesn't it makes sence that we want to move every members ( if we can't copy them )?
Edit: I just tried something and it seems to work, just declare the move operators using default. This is the way to go I suppose. But the "why" question remains.
Edit2: Another example
class Test
{
public:
Test()
{
m_vec.resize( 10 );
}
Test( const Test& ) = delete;
Test& operator=( const Test& ) = delete;
//Test( Test&& ) = default;
//Test& operator=( Test&& ) = default;
void cout()
{
std::cout << m_vec.size() << std::endl;
}
private:
std::vector< int > m_vec;
};
int main()
{
Test a;
std::vector< Test > v;
v.push_back( std::move( a ) );
v[ 0 ].cout();
}
I have to explicitely write move constructor/move assignment operators:
This is where you are wrong. Either do not write them at all and let the compiler, or =default; them.
SomeClass a;
m_vector.push_back( a );
You did that wrong, it must be:
SomeClass a;
m_vector.push_back( std::move(a) );
Related
I have a class with one strong pointer and a lot of object members. Writing copy and move constructors for an object like this involves a lot of tedious copy/pasting, however...
Is there any way to shorten this, without giving up my beautiful naked pointer? Like if I could perform the default generated move operation, with just one extra instruction to nullify the naked pointer afterwards?
class Example {
public:
Example()
: m_multiplexDevice(getDevice(B737M_mpDevice, true))
{
engageDevice(m_multiplexDevice);
}
Example(Example && other)
: m_multiplexDevice (other.m_multiplexDevice )
, m_pilotStack (std::move(other.m_pilotStack ))
, m_pasStack (std::move(other.m_pasStack ))
, m_pitchAttackLimits (std::move(other.m_pitchAttackLimits))
, m_yawToPitchBalance (std::move(other.m_yawToPitchBalance))
, m_engineBalance (std::move(other.m_engineBalance ))
{
other.m_multiplexDevice = NULL;
}
Example & operator=(Example && other) {
if (this != &other) {
// ignore that this is incorrect (not properly destroying in assignment),
// working with client code that kinda sucks
m_multiplexDevice = other.m_multiplexDevice;
m_pilotStack = std::move(other.m_pilotStack );
m_pasStack = std::move(other.m_pasStack );
m_pitchAttackLimits = std::move(other.m_yawToPitchBalance );
m_yawToPitchBalance = std::move(other.m_yawToPitchBalance );
m_engineBalance = std::move(other.m_engineBalance );
m_multiplexDevice = NULL;
}
return *this;
}
Example(const Example & other) =delete;
Example & operator=(const Example & other) =delete;
~Example() {
if (m_multiplexDevice)
disengageDevice(m_multiplexDevice);
delete m_multiplexDevice;
}
private:
char STRONG * m_multiplexDevice;
std::vector<uint32> m_pilotStack;
std::vector<uint32> m_pasStack;
std::vector<uint32> m_pitchAttackLimits;
std::vector<uint32> m_yawToPitchBalance;
std::vector<uint32> m_engineBalance;
// ... etc
};
Use a unique_ptr with a custom deleter.
#include <memory>
#include <vector>
#include <cstdint>
#define STRONG /* ??? */
void disengageDevice(char STRONG*);
#define B737M_mpDevice 1
char STRONG *getDevice(int, ...);
void engageDevice(char STRONG *);
class Example {
public:
Example()
: m_multiplexDevice(
getDevice(B737M_mpDevice, true),
deconstruct_m_multiplexDevice)
{
engageDevice(m_multiplexDevice.get());
}
static void deconstruct_m_multiplexDevice(char STRONG *p) {
if (p) {
disengageDevice(p);
delete p;
}
}
private:
std::unique_ptr<
char STRONG,
decltype(&deconstruct_m_multiplexDevice)
> m_multiplexDevice;
std::vector<uint32_t> m_pilotStack;
std::vector<uint32_t> m_pasStack;
std::vector<uint32_t> m_pitchAttackLimits;
std::vector<uint32_t> m_yawToPitchBalance;
std::vector<uint32_t> m_engineBalance;
// ... etc
};
In c++ when classes contains dynamically allocated data it is usually reasonable to explicitly define copy constructor, operator= and destructor. But the activity of these special methods overlaps. More specifically operator= usually first does some destruction and then it does coping similar to the one in copy constructor.
My question is how to write this the best way without repeating the same lines of code and without the need for processor to do unnecessary work (like unnecessary copying).
I usually end up with two helping methods. One for construction and one for destruction. The first is called from both copy constructor and operator=. The second is used by destructor and operator=.
Here is the example code:
template <class T>
class MyClass
{
private:
// Data members
int count;
T* data; // Some of them are dynamicly allocated
void construct(const MyClass& myClass)
{
// Code which does deep copy
this->count = myClass.count;
data = new T[count];
try
{
for (int i = 0; i < count; i++)
data[i] = myClass.data[i];
}
catch (...)
{
delete[] data;
throw;
}
}
void destruct()
{
// Dealocate all dynamicly allocated data members
delete[] data;
}
public: MyClass(int count) : count(count)
{
data = new T[count];
}
MyClass(const MyClass& myClass)
{
construct(myClass);
}
MyClass& operator = (const MyClass& myClass)
{
if (this != &myClass)
{
destruct();
construct(myClass);
}
return *this;
}
~MyClass()
{
destruct();
}
};
Is this even correct?
And is it a good habit to split the code this way?
One initial comment: the operator= does not start by
destructing, but by constructing. Otherwise, it will leave the
object in an invalid state if the construction terminates via an
exception. Your code is incorrect because of this. (Note that
the necessity to test for self assignment is usually a sign that
the assignment operator is not correct.)
The classical solution for handling this is the swap idiom: you
add a member function swap:
void MyClass:swap( MyClass& other )
{
std::swap( count, other.count );
std::swap( data, other.data );
}
which is guaranteed not to throw. (Here, it just swaps an int
and a pointer, neither of which can throw.) Then you
implement the assignment operator as:
MyClass& MyClass<T>::operator=( MyClass const& other )
{
MyClass tmp( other );
swap( tmp );
return *this;
}
This is simple and straight forward, but any solution in which
all operations which may fail are finished before you start
changing the data is acceptable. For a simple case like your
code, for example:
MyClass& MyClass<T>::operator=( MyClass const& other )
{
T* newData = cloneData( other.data, other.count );
delete data;
count = other.count;
data = newData;
return *this;
}
(where cloneData is a member function which does most of what
your construct does, but returns the pointer, and doesn't
modify anything in this).
EDIT:
Not directly related to your initial question, but generally, in
such cases, you do not want to do a new T[count] in
cloneData (or construct, or whatever). This constructs all
of the T with the default constructor, and then assigns them.
The idiomatic way of doing this is something like:
T*
MyClass<T>::cloneData( T const* other, int count )
{
// ATTENTION! the type is a lie, at least for the moment!
T* results = static_cast<T*>( operator new( count * sizeof(T) ) );
int i = 0;
try {
while ( i != count ) {
new (results + i) T( other[i] );
++ i;
}
} catch (...) {
while ( i != 0 ) {
-- i;
results[i].~T();
}
throw;
}
return results;
}
Most often, this will be done using a separate (private) manager
class:
// Inside MyClass, private:
struct Data
{
T* data;
int count;
Data( int count )
: data( static_cast<T*>( operator new( count * sizeof(T) ) )
, count( 0 )
{
}
~Data()
{
while ( count != 0 ) {
-- count;
(data + count)->~T();
}
}
void swap( Data& other )
{
std::swap( data, other.data );
std::swap( count, other.count );
}
};
Data data;
// Copy constructor
MyClass( MyClass const& other )
: data( other.data.count )
{
while ( data.count != other.data.count ) {
new (data.data + data.count) T( other.date[data.count] );
++ data.count;
}
}
(and of course, the swap idiom for assignment). This allows
multiple count/data pairs without any risk of loosing exception
safety.
I don't see any inherent problem with that, as long as you make sure not to declare construct or destruct virtual.
You might be interested in chapter 2 in Effective C++ (Scott Meyers), which is completely devoted to constructors, copy operators and destructors.
As for exceptions, which your code is not handling as it should, consider items 10 & 11 in More effective C++ (Scott Meyers).
Implement the assignment by first copying the right-hand side and then swapping with that. This way you also get exception safety, which your code above doesn't provide. You could end up with a broken container when construct() fails after destruct() succeeded otherwise, because the member pointer references some deallocated data, and on destruction that will be deallocated again, causing undefined behaviour.
foo&
foo::operator=(foo const& rhs)
{
using std::swap;
foo tmp(rhs);
swap(*this, tmp);
return *this;
}
Basically what I want is:
class MyClass{
public:
MyClass() = default;
// what should I do?
}
MyClass mc; // compile time error;
auto pmc = new MyClass; //OK
delete pmc; //OK too
I know I can make it heap-only by hiding constructor (can not new outside of the class now) or hiding destructor (can not delete outside of the class now) or hiding both. What if I don't want to introduce some new named function and just want the good old new and delete? Is it possible (even with hack)?
My "like a smart pointer, but not" idea:
#include <iostream>
class MyClass_ {
private:
/**/ MyClass_( void ) { }
/**/ ~MyClass_( void ) { }
public:
void func( void ) const { std::cout << "Hello" << std::endl; }
friend class MyClass;
} ;
class MyClass {
public:
/**/ MyClass( void ) : p( new MyClass_ ) { }
/**/ ~MyClass( void ) { delete p; }
// Tricky implementation details follow...
// The question in all cases is, who owns the MyClass_ that has been
// allocated on the heap? Do you always allocate a new one, and then
// copy the guts? (That might be expensive!) Do you change ownership?
// Then what about the other MyClass? What does it point to?
// Or do you share ownership? Then you need to ref-count so you don't
// delete too soon. (And this whole thing turns into an ordinary
// shared_ptr<MyClass_>)
/**/ MyClass( const MyClass &o ) { }
/**/ MyClass( MyClass &&o ) { }
MyClass &operator=( const MyClass &o ) { }
MyClass &operator=( MyClass &&o ) { }
MyClass_ * operator->( void ) { return p; }
const MyClass_ * operator->( void ) const { return p; }
private:
MyClass_ *p;
} ;
int
main( int, char ** )
{
MyClass a; // this will be destroyed properly
MyClass *b = new MyClass; // this will leak if you don't delete it
a->func( );
(*b)->func( );
return 0;
}
This is going to sound like not-what-you-want, but surround it in another class. That way you can enforce your storage is allocated off of the heap, and keep such details away from your API user.
A usual way would be to make your constructor private, and add some static member function (you could call it a factory or making function) which returns a pointer.
So your class would look like
class MyClass{
private:
MyClass() = default;
public:
static MyClass* make() { return new MyClass; };
// what should I do?
}
and you'll code:
auto mc = MyClass::make();
elsewhere (instead of new MyClass)
etc. However be aware of the rule of five and consider using (as return type of your MyClass::make) some smart pointer from the <memory> header.
You could also define your own smart pointer class with its own unary operator -> and operator * and your own variadic templates inspired by std::make_shared ...
just want the good old new and delete
In genuine C++11, this is frowned upon and may be considered bad style. You should avoid using explicitly new outside of your library, and adopt some smart pointer way of coding.
I have a container class for some unique pointers to objects.
I now need to take one of them, do something with them in a different class and hand over to another class (and at some point recycle them and put them back to the container ).
Below is the outline of the code. However I am getting confused with the right way to move unique pointers with functions:
using uptrPod = unique_ptr<Pod>;
using dqUptrPods = deque<uptrPods>;
class Container {
public:
Container() :
n_elements_( 500 )
{
for ( auto i = 0; i < n_elements_; i++ ) {
free_pods_.push_back( uptrPod( new Pod()) );
}
const uptrPod&& getPod() {
auto up_pod= std::move( free_pods_[0] );
free_pods_.erase( free_pods_.begin() );
return up_pod;
}
void returnPod( const uptrPod&& up_pod ) {
free_pods_.push_back( up_pod );
}
private:
long n_elements_;
dqUptrPods free_pods_;
};
class PodTracker {
void addPod( const uptrPod&& up_pod ) { dq_pods_.pushback( up_pod ); }
dqUptrPods dq_pods_;
};
class PodHandler {
void movePod() {
up_pod = std::move( container_->getPod() );
/// do stuff with pod
pod_tracker_->addPod( up_pod );
}
Container* container_;
PodTracker* pod_tracker_;
};
I am getting the error:
cannot bind std::unique_ptr l value to const uptrPod&& { aka const std::unique_ptr &&
How can I hand around the pointer between the classes?
Pass/return the std::unique_ptr instances by value, and explicitly use std::move:
uptrPod getPod() {
auto up_pod= std::move( free_pods_[0] );
free_pods_.erase( free_pods_.begin() );
return up_pod;
}
void returnPod( uptrPod up_pod ) {
free_pods_.push_back( std::move(up_pod) );
}
class PodTracker{
void addPod(uptrPod up_pod) { dq_pods_.push_back(std::move(up_pod)); }
dqSptrPods dq_pods_;
};
void movePod() {
// `std::move` is not necessary here, as `getPod()`
// is already a temporary (rvalue)
auto up_pod = container_->getPod();
/// do stuff with pod
pod_tracker_->addPod( std::move(up_pod) ) ;
}
example on wandbox
Note that const rvalue references do not make much sense - an rvalue reference.
The main purpose of rvalue references is to allow us to move objects instead of copying them. And moving the state of an object implies modification. As a result, the canonical signatures for the move constructor and the move assignment operator both take its argument as a non-const rvalue reference.
(From: "What are const rvalue references good for?")
In c++ when classes contains dynamically allocated data it is usually reasonable to explicitly define copy constructor, operator= and destructor. But the activity of these special methods overlaps. More specifically operator= usually first does some destruction and then it does coping similar to the one in copy constructor.
My question is how to write this the best way without repeating the same lines of code and without the need for processor to do unnecessary work (like unnecessary copying).
I usually end up with two helping methods. One for construction and one for destruction. The first is called from both copy constructor and operator=. The second is used by destructor and operator=.
Here is the example code:
template <class T>
class MyClass
{
private:
// Data members
int count;
T* data; // Some of them are dynamicly allocated
void construct(const MyClass& myClass)
{
// Code which does deep copy
this->count = myClass.count;
data = new T[count];
try
{
for (int i = 0; i < count; i++)
data[i] = myClass.data[i];
}
catch (...)
{
delete[] data;
throw;
}
}
void destruct()
{
// Dealocate all dynamicly allocated data members
delete[] data;
}
public: MyClass(int count) : count(count)
{
data = new T[count];
}
MyClass(const MyClass& myClass)
{
construct(myClass);
}
MyClass& operator = (const MyClass& myClass)
{
if (this != &myClass)
{
destruct();
construct(myClass);
}
return *this;
}
~MyClass()
{
destruct();
}
};
Is this even correct?
And is it a good habit to split the code this way?
One initial comment: the operator= does not start by
destructing, but by constructing. Otherwise, it will leave the
object in an invalid state if the construction terminates via an
exception. Your code is incorrect because of this. (Note that
the necessity to test for self assignment is usually a sign that
the assignment operator is not correct.)
The classical solution for handling this is the swap idiom: you
add a member function swap:
void MyClass:swap( MyClass& other )
{
std::swap( count, other.count );
std::swap( data, other.data );
}
which is guaranteed not to throw. (Here, it just swaps an int
and a pointer, neither of which can throw.) Then you
implement the assignment operator as:
MyClass& MyClass<T>::operator=( MyClass const& other )
{
MyClass tmp( other );
swap( tmp );
return *this;
}
This is simple and straight forward, but any solution in which
all operations which may fail are finished before you start
changing the data is acceptable. For a simple case like your
code, for example:
MyClass& MyClass<T>::operator=( MyClass const& other )
{
T* newData = cloneData( other.data, other.count );
delete data;
count = other.count;
data = newData;
return *this;
}
(where cloneData is a member function which does most of what
your construct does, but returns the pointer, and doesn't
modify anything in this).
EDIT:
Not directly related to your initial question, but generally, in
such cases, you do not want to do a new T[count] in
cloneData (or construct, or whatever). This constructs all
of the T with the default constructor, and then assigns them.
The idiomatic way of doing this is something like:
T*
MyClass<T>::cloneData( T const* other, int count )
{
// ATTENTION! the type is a lie, at least for the moment!
T* results = static_cast<T*>( operator new( count * sizeof(T) ) );
int i = 0;
try {
while ( i != count ) {
new (results + i) T( other[i] );
++ i;
}
} catch (...) {
while ( i != 0 ) {
-- i;
results[i].~T();
}
throw;
}
return results;
}
Most often, this will be done using a separate (private) manager
class:
// Inside MyClass, private:
struct Data
{
T* data;
int count;
Data( int count )
: data( static_cast<T*>( operator new( count * sizeof(T) ) )
, count( 0 )
{
}
~Data()
{
while ( count != 0 ) {
-- count;
(data + count)->~T();
}
}
void swap( Data& other )
{
std::swap( data, other.data );
std::swap( count, other.count );
}
};
Data data;
// Copy constructor
MyClass( MyClass const& other )
: data( other.data.count )
{
while ( data.count != other.data.count ) {
new (data.data + data.count) T( other.date[data.count] );
++ data.count;
}
}
(and of course, the swap idiom for assignment). This allows
multiple count/data pairs without any risk of loosing exception
safety.
I don't see any inherent problem with that, as long as you make sure not to declare construct or destruct virtual.
You might be interested in chapter 2 in Effective C++ (Scott Meyers), which is completely devoted to constructors, copy operators and destructors.
As for exceptions, which your code is not handling as it should, consider items 10 & 11 in More effective C++ (Scott Meyers).
Implement the assignment by first copying the right-hand side and then swapping with that. This way you also get exception safety, which your code above doesn't provide. You could end up with a broken container when construct() fails after destruct() succeeded otherwise, because the member pointer references some deallocated data, and on destruction that will be deallocated again, causing undefined behaviour.
foo&
foo::operator=(foo const& rhs)
{
using std::swap;
foo tmp(rhs);
swap(*this, tmp);
return *this;
}