Understanding std::move and its purpose by example [duplicate] - c++

This question already has answers here:
What is move semantics?
(11 answers)
Closed 2 years ago.
Consider the following code:
class c
{
large_type_t i;
public:
// the most simple variant
c( large_type_t i ): i( i ) { }
// move the parameter copied
c( large_type_t i ): i( std::move( i ) ) { }
// copy is done directly in interaction with our class member from original
c( const large_type_t &i ): i( i ) { }
// parameter was constructed in the call, just treat as rvalue
c( large_type_t &&i ): i( std::move( i ) ) { }
// this is here just to show all possible combinations in case someone in the future sees this question and someone answering it wants to explain everything
c( large_type_t &&i ): i( i ) { }
};
What is the best way to do this? Are these all going to boil down to the same code anyway and it doesn't matter? I feel that I am fundamentally not understanding the purpose of move.

Move constructors (or move assignments) provide the means for your program to avoid spending excessive time copying the contents of one object to another, if the copied-from object will no longer be used afterwards. For example, when an object is to be the returned value of a method or function.
This is more obvious when you have an object with, say, dynamically allocated content.
Example:
class MyClass {
private:
size_t _itemCount ;
double * _bigBufferOfDoubles ;
public:
// ... Initial contructor, creating a big list of doubles
explicit MyClass( size_t itemCount ) {
_itemCount = itemCount ;
_bigBufferOfDoubles = new double[ itemCount ];
}
// ... Copy constructor, to be used when the 'other' object must persist
// beyond this call
MyClass( const MyClass & other ) {
//. ... This is a complete copy, and it takes a lot of time
_itemCount = other._itemCount ;
_bigBufferOfDoubles = new double[ _itemCount ];
for ( int i = 0; i < itemCount; ++i ) {
_bigBufferOfDoubles[ i ] = other. _bigBufferOfDoubles[ i ] ;
}
}
// ... Move constructor, when the 'other' can be discarded (i.e. when it's
// a temp instance, like a return value in some other method call)
MyClass( MyClass && other ) {
// ... Blazingly fast, as we're just copying over the pointer
_itemCount = other._itemCount ;
_bigBufferOfDoubles = other._bigBufferOfDoubles ;
// ... Good practice to clear the 'other' as it won't be needed
// anymore
other._itemCount = 0 ;
other._bigBufferOfDoubles = null ;
}
~MyClass() {
delete [] _bigBufferOfDoubles ;
}
};
// ... Move semantics are useful to return an object 'by value'
// Since the returned object is temporary in the function,
// the compiler will invoke the move constructor of MyClass
MyClass someFunctionThatReturnsByValue() {
MyClass myClass( 1000000 ) ; // a really big buffer...
return myClass ; // this will call the move contructor, NOT the copy constructor
}
// ... So far everything is explicitly handled without an explicit
// call to std::move
void someOtherFunction() {
// ... You can explicitly force the use of move semantics
MyClass myTempClass( 1000000 ) ;
// ... Say I want to make a copy, but I don't want to invoke the
// copy contructor:
MyClass myOtherClass( 1 ) ;
myOtherClass = std::move( myTempClass ) ;
// ... At this point, I should abstain from using myTempClass
// as its contents have been 'transferred' over to myOtherClass.
}

What is the best way to do this?
The simplest variant. The reason: Because it is the simplest variant.
Trivial types do not have copy constructors nor move constructors, and "moving" them is same as copying.
Are these all going to boil down to the same code anyway and it doesn't matter?
If optimisation and in particular inline expansion is involved, then probably yes. You can verify whether that is the case for your program by comparing the resulting assembly. Assuming no (or poor) optimisation, the simplest variant is potentially fastest.
Regarding your edit: For non-trivial types, the second variant is best because it moves from rvalue arguments instead of copying.

All of those are different and it very much depends on what large_type_t i; is.
Does it manage dynamically allocated data? If yes and it supports both moving and copy construction then following two constuctors should be used:
c( const large_type_t &i ): mi( i ) { };
c( large_type_t &&i ): mi( std::move( i ) ) {};
Although, it is potentially a mildly less efficient way, but you can use a single constructor for both purposes:
c( large_type_t i): mi( std::move( i ) ) { };
For the above, without std::move it will likely result in unnecessary copying and memory allocations.
If it doesn't manage any dynamically allocated data - then usually moving/copying is the same thing (for exotic types figure it yourself since it's too dependent on circumstances). Thus you only need copy constructor:
c( const large_type_t &i ): mi( i ) { };
For small trivial types, you'd better use the most basic form:
c( small_type_t i ): mi( i ) { };

Related

I need the option of passing in a vector of objects, or brace-enclosed list, to a constructor

My constructor originally took a std::vector<> but I couldn't figure out how to get a braced list to initialize it. I got it working after changing to an std:initializer_list<>. I found two ways: 1) passing the initializer_list in as a parameter to the array constructor (commented out in code below) and 2) using the std::copy algo (as seen in code below).
Now, I need to create this object with a std::vector<> and can't figure out how to convert it to the initializer_list. I could make a second constructor that takes a vector, but as an exercise I'd like to get this working with one constructor if possible.
Any ideas?
class One: public Base {
public:
One( Two* ptwo_in, std::initializer_list<Three> ilthree ) :
ptwo( ptwo_in )//,
//athree_( ilthree )
{
athree_.reserve( ilthree .size() );
std::copy( ilthree .begin(), ilthree .end(), athree_.begin() );
}
Two* ptwo_;
std::vector<Three> athree_;
};
// Works fine:
new One( &two, { Three( args ),
Three( args ),
Three( args ), } )
// Doesn't work:
std::vector<Three>* pathreeSomething
athreeOther.push_back( new One( ptwoLocal, *pathreeSomething ) );
On that third line of code it works with replacing initializer_list with vector, true. But I don't want to pass around a whole vector as an arg.
You're going to construct a vector anyway (One::athree_). So just move the vector passed to the constructor rather than copy it:
class One: public Base {
public:
One(Two* ptwo_in, std::vector<Three> ilthree)
: ptwo{ptwo_in}
, athree_{std::move(ilthree)}
{ }
private:
Two* ptwo_;
std::vector<Three> athree_;
};
This is a common pattern in C++. Pass by non-const value and use move semantics to avoid copies:
One one{some_ptr, {Three{args}, Three{args}, Three{args}}};
or:
std::vector<Three> vec{ ... };
// moves 'vec' to the ctor parameter, the ctor then moves it to its member
One one{some_ptr, std::move(vec)};
No unnecessary copies that way.

c++ vector without pointers

I have a std::vector<Enemy*> enemies and when i create a new Enemy i do enemies.push_back(this). This works for what i'm doing, but i'm wondering if there is a way to have the vector not need pointers to the enemies. I've tried just std::vector<Enemy> but it seems to cause a bunch of problems i can't figure out.
ie. - had to change to enemies.push_back(*this), and it caused some linker errors for some reason.
looping through with the following works, but removing the pointers creates issues:
void Enemy::updateEnemies(sf::RenderWindow &window) {
for(std::vector<Enemy*>::iterator it = enemies.begin(); it < enemies.end(); it++) {
(*it)->update(window);
}
}
Wondering if someone could point me in the direction of using a vector without pointers and loop through it, updating the objects inside it with the same function..
everbody is saying it in comments - but its the answer
use smart pointers
if you dont know how to do that then google
You life is much easier, safer, faster,...
And they are really easy to use - the main trick with using them is to trust them and dont try to get clever or 'help' them
My practice is to make sure the class implements (and makes public) all of the following: a default constructor, a copy constructor, an assignment operator, and a destructor. Then there's no problem with things like std::vector<Enemy>. (The default constructor isn't even necessary for vectors, but can be handy for various other things.)
One caveat, though: when you push_back() an Enemy into your vector, it's actually a copy of the original instance that gets stored. This raises a few gotchas: first, changes to the original (e.g. to the member data of the variable e in the main() scope of my example below) will not affect the copy stored in the vector. If you're accustomed to working with vectors-of-pointers, this may be surprising. Second, the implicit construction of copies and the copying of member data will take time, which may or may not have a significant effect on performance. Third, implicit construction and copying may trigger side-effects (you should simply avoid these in your design, wherever possible).
Here's an example:
#include <vector>
#include <iostream>
class Enemy
{
public:
Enemy() : mEvilness( 1 ) {} // default (i.e. parameterless) constructor
Enemy( const Enemy& other ) { Copy( other ); } // copy constructor
Enemy& operator=( const Enemy& other ) { return Copy( other ); } // assignment operator
~Enemy() {} // destructor
Enemy( int evilness ) : mEvilness( evilness ) {} // standard constructor
void Gloat( void ) const
{
std::cout << "muahaha";
for( int i = 0; i < mEvilness; i++ ) std::cout << "ha";
std::cout << "!\n";
}
int mEvilness;
private:
// common helper method for copy constructor and assignment operator:
Enemy& Copy( const Enemy& other )
{
mEvilness = other.mEvilness; // make copies of any other member data here
return *this;
}
};
typedef std::vector< Enemy > EnemyHorde;
void AllGloat1( const EnemyHorde& h ) // doesn't matter if you pass by reference...
{
for( EnemyHorde::const_iterator it = h.begin(); it != h.end(); it++ )
it->Gloat();
}
void AllGloat2( EnemyHorde h ) // ...or value (but this will take more CPU time)
{
for( EnemyHorde::const_iterator it = h.begin(); it != h.end(); it++ )
it->Gloat();
}
int main( int argc, const char* argv[] )
{
EnemyHorde h;
Enemy e( 1 );
h.push_back( e );
h.push_back( Enemy( 2 ) ); // even transient Enemy instances get copied and stored
h.push_back( Enemy( 3 ) );
AllGloat1( h );
std::cout << "\n";
e.mEvilness++; // this will have no effect on the output because h contains a *copy* of e
AllGloat2( h );
return 0;
}
If you want a well-founded answer you have to go one step back - to the design. As far as i see the Enemy objects are registering themselves via constructor in a kind of global list. So far so good.
But how these object are produced ? In this example in Enemy can be construct everywhere
On the stack as local
By new (smartpointer)
As an element in a vector, list, deque ...
...
Depending on this, the Enemy-object cant do any reliable statements about its storage. But one thing that all objects share and what is always accessible from inside the object - is the address ('this'). So the solution via pointer is the only solution that is universal for all constructed Enemy-objects. (References are in this context also "a kind of pointer", and other more complicate constructs may also rely on pointers).
A std::vector cant work because you get 2 different objects. To change one of them does not effect the other. That wont work. And it is not possible to switch to smart pointers without changing your design.
There are 2 common solutions:
Managing the listing from 'inside' Enemy in a generally way like in the given example. Expandable with more features like auto delete entries via destructor.....
Managing the listing from 'outside'. Enemy-objects dont register themselves, the generator of the Enemy-objects is responsible for to do it proper (the design pattern 'factory' is a good solution in this case). And you can use smart pointers what is a good idea in most cases.
There are also some more solutions (including some good solutions) unmentioned, they exceed the scope of the question.
You don't need pointers (most of the time) in C++.
A copy will be made when using the std::vector::push_back() method.
Example:
Enemy evil_wizard;
std::vector<Enemy> enemy_container;
enemy_container.push_back(evil_wizard);
Enemy Evil_knight;
enemy_container.push_back(Evil_knight);
Enemy pink_elephant;
enemy_container.push_back(pink_elephant);

Replacing a non-copyable, non-movable object

Consider the following code:
// A non-copyable, non-movable aggregate
struct Strange
{
const int & i;
char & c;
};
class Container
{
private:
int my_i;
char my_c;
Strange thing;
public:
// Valid, because both `my_i´ and `my_c´ are non-const
// objects to which both references can be bound.
explicit
Container
( )
noexcept
: thing{ my_i , my_c }
{ }
// How could this be implemented?
auto &
operator=
( const Container & that )
noexcept
{
this->my_i = that->my_i;
this->my_c = that->my_c;
// What to do with `thing´?
return *this;
}
};
Possible solutions
Dynamically allocate the Strange object
class Container
{
private:
int my_i;
char my_c;
Strange * thing;
public:
// Note that it isn't exception safe.
explicit
Container
( )
: thing(new Strange{ my_i , my_c })
{ }
auto &
operator=
( const Container & that )
noexcept
{
this->my_i = that->my_i;
this->my_c = that->my_c;
delete this->thing;
this->thing = new Strange { this->my_i , this->my_c };
return *this;
}
};
Concerns:
Not efficient.
Not safe: allocation may fail and throw.
Dangerous: great care has to be taken not to leak memory.
Using a smart pointer (i.e. std::unique_ptr) would solve only the last point, aside from making the code more readable.
Use placement new
class Container
{
private:
int my_i;
char my_c;
Strange thing;
public:
explicit
Container
( )
noexcept
: thing{ my_i , my_c }
{ }
auto &
operator=
( const Container & that )
noexcept
{
this->my_i = that.my_i;
this->my_c = that.my_c;
// Placement new is exception safe, and so is
// construction of `Strange´.
this->thing.~Strange();
new(&this->thing) Strange { this->my_i , this->my_c };
return *this;
}
};
Concerns:
Will Strange's destructor free the memory taken by thing?
I think that, just as constructors, destructors are not responsible for memory management. Moreover, my code seems to work fine. However, I would like clarification on this.
What about memory alignment?
My guess is that, since it replaces an existing object of the same type, memory would already be aligned. Is this correct?
Would Container's destructor take care of destructing thing?
Questions
Aside from corroborating and/or refuting the concerns I explained above, I would like to know if there are other alternatives. If so, please, give an example implementation.
This question arose when working on a class that ought to offer an interface similar to that of std::unordered_map. Instead of reimplementing it, my class encapsulates such container, and just acts as a proxy for most methods: its iterators envelop those provided by the map, and its pair is an aggregate structure with appropiately named members (which are references to the actual data), represented in the examples provided as Strange. Since iterators are required to return references and pointers to the actual data, my custom iterators contain a pair. The problem was modifying it (when incrementing or assigning the iterator). I acknowledge that this probably isn't a good idea, and that those references will impact performance, but am anyway interested in the matter.
Edit
I have just realized that, instead of returning references and pointers to a member custom pair pointing to the actual data (that of the encapsulated map) from my custom iterator, I could return in-place constructed custom pairs (i.e. Strange objects). Often, we do not see that we are in a cave, and instead of exiting it, continue forward :). Excuse me for the noise, I'll mark the question as "Closed".
(If we're talking about moving objects and using the auto keyword, you should add the c++11 tag to your question).
I'm not sure I really understand your question; the example you gave doesn't seem well thought to me; it would be much better to use pointers in Strange.
For example, this compiles and works absolutely fine, and is functionally equivalent to what you want to do I think.
struct Strange
{
Strange()
: i(nullptr), c(nullptr) {}
Strange( const int *_i, const char *_c )
: i(_i), c(_c) {}
const int *i;
const char *c;
};
class Container
{
int my_i;
char my_c;
Strange thing;
public:
Container()
: thing(&my_i,&my_c)
{ }
Container( int i, char c )
: my_i(i), my_c(c), thing(&my_i,&my_c)
{ }
Container( int i, char c, const Strange& s )
: my_i(i), my_c(c), thing(s) // use default copy-constructor
{ }
Container &
operator=
( const Container & that )
{
my_i = that.my_i;
my_c = that.my_c;
thing = that.thing;
return *this;
}
};
int main()
{
Container a(12,24);
Container b(25,42);
b = a;
}
Note that referencing memory within objects is generally dangerous.
For example, using memcpy on this would be a catastrophy.
(Compiled with clang and g++)

Thread-safe lock-free array

I have a C++ library, which supposed to do some computations on multiple threads. I made independent threads code (i.e. there are no shared variables between them), except for one array. The problem is, I don't know how to make it thread-safe.
I looked at mutex lock/unlock (QMutex, as I'm using Qt), but it doesn't fit for my task - while one thread will lock the mutex, other threads will wait!
Then I read about std::atomic, which looked like exactly what I needed. Nevertheless, I tried to use it in the following way:
std::vector<std::atomic<uint64_t>> *myVector;
And it produced compiler error (use of deleted function 'std::atomic::atomic(const std::atomic&)'). Then I found the solution - use special wrapper for std::atomic. I tried this:
struct AtomicUInt64
{
std::atomic<uint64_t> atomic;
AtomicUInt64() : atomic() {}
AtomicUInt64 ( std::atomic<uint64_t> a ) : atomic ( atomic.load() ) {}
AtomicUInt64 ( AtomicUInt64 &auint64 ) : atomic ( auint64.atomic.load() ) {}
AtomicUInt64 &operator= ( AtomicUInt64 &auint64 )
{
atomic.store ( auint64.atomic.load() );
}
};
std::vector<AtomicUInt64> *myVector;
This thing compiles succesfully, but when I can't fill the vector:
myVector = new std::vector<AtomicUInt64>();
for ( int x = 0; x < 100; ++x )
{
/* This approach produces compiler error:
* use of deleted function 'std::atomic<long long unsigned int>::atomic(const std::atomic<long long unsigned int>&)'
*/
AtomicUInt64 value( std::atomic<uint64_t>( 0 ) ) ;
myVector->push_back ( value );
/* And this one produces the same error: */
std::atomic<uint64_t> value1 ( 0 );
myVector->push_back ( value1 );
}
What am I doing wrong? I assume I tried everything (maybe not, anyway) and nothing helped. Are there any other ways for thread-safe array sharing in C++?
By the way, I use MinGW 32bit 4.7 compiler on Windows.
Here is a cleaned up version of your AtomicUInt64 type:
template<typename T>
struct MobileAtomic
{
std::atomic<T> atomic;
MobileAtomic() : atomic(T()) {}
explicit MobileAtomic ( T const& v ) : atomic ( v ) {}
explicit MobileAtomic ( std::atomic<T> const& a ) : atomic ( a.load() ) {}
MobileAtomic ( MobileAtomic const&other ) : atomic( other.atomic.load() ) {}
MobileAtomic& operator=( MobileAtomic const &other )
{
atomic.store( other.atomic.load() );
return *this;
}
};
typedef MobileAtomic<uint64_t> AtomicUInt64;
and use:
AtomicUInt64 value;
myVector->push_back ( value );
or:
AtomicUInt64 value(x);
myVector->push_back ( value );
your problem was you took a std::atomic by value, which causes a copy, which is blocked. Oh, and you failed to return from operator=. I also made some constructors explicit, probably needlessly. And I added const to your copy constructor.
I would also be tempted to add store and load methods to MobileAtomic that forwards to atomic.store and atomic.load.
You're trying to copy a non-copyable type: the AtomicUInt64 constructor takes an atomic by value.
If you need it to be initialisable from atomic, then it should take the argument by (const) reference. However, in your case, it doesn't look like you need to initialise from atomic at all; why not initialise from uint64_t instead?
Also a couple of minor points:
The copy constructor and assignment operator should take their values by const reference, to allow temporaries to be copied.
Allocating the vector with new is a rather odd thing to do; you're just adding an extra level of indirection with no benefit.
Make sure you never resize the array while other threads might be accessing it.
This line
AtomicUInt64 ( std::atomic<uint64_t> a ) : atomic ( atomic.load() ) {}
You're completely ignoring the argument you pass in, You probably want it to be a.load() and you probably want to take elements by const reference so they aren't copied.
AtomicUInt64 (const std::atomic<uint64_t>& a) : atomic (a.load()) {}
As for what you're doing, I'm not sure if it is correct. The modification of the variables inside the array will be atomic, but if the vector is modified or reallocated (which is possible with push_back), then there's nothing to guarantee your array modifications will work between threads and be atomic.

Declaring an object before initializing it in c++

Is it possible to declare a variable in c++ without instantiating it? I want to do something like this:
Animal a;
if( happyDay() )
a( "puppies" ); //constructor call
else
a( "toads" );
Basially, I just want to declare a outside of the conditional so it gets the right scope.
Is there any way to do this without using pointers and allocating a on the heap? Maybe something clever with references?
You can't use references here, since as soon as you'd get out of the scope, the reference would point to a object that would be deleted.
Really, you have two choices here:
1- Go with pointers:
Animal* a;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
// ...
delete a;
or with a smart pointer
#include <memory>
std::unique_ptr<Animal> a;
if( happyDay() )
a = std::make_unique<Animal>( "puppies" );
else
a = std::make_unique<Animal>( "toads" );
2- Add an Init method to Animal:
class Animal
{
public:
Animal(){}
void Init( const std::string& type )
{
m_type = type;
}
private:
std:string m_type;
};
Animal a;
if( happyDay() )
a.Init( "puppies" );
else
a.Init( "toads" );
I'd personally go with option 2.
You can't declare a variable without calling a constructor. However, in your example you could do the following:
Animal a(happyDay() ? "puppies" : "toads");
You can't do this directly in C++ since the object is constructed when you define it with the default constructor.
You could, however, run a parameterized constructor to begin with:
Animal a(getAppropriateString());
Or you could actually use something like the ?: operator to determine the correct string.
(Update: #Greg gave the syntax for this. See that answer)
I prefer Greg's answer, but you could also do this:
char *AnimalType;
if( happyDay() )
AnimalType = "puppies";
else
AnimalType = "toads";
Animal a(AnimalType);
I suggest this because I've worked places where the conditional operator was forbidden. (Sigh!) Also, this can be expanded beyond two alternatives very easily.
If you want to avoid garbage collection - you could use a smart pointer.
auto_ptr<Animal> p_a;
if ( happyDay() )
p_a.reset(new Animal( "puppies" ) );
else
p_a.reset(new Animal( "toads" ) );
// do stuff with p_a-> whatever. When p_a goes out of scope, it's deleted.
If you still want to use the . syntax instead of ->, you can do this after the code above:
Animal& a = *p_a;
// do stuff with a. whatever
In addition to Greg Hewgill's answer, there are a few other options:
Lift out the main body of the code into a function:
void body(Animal & a) {
...
}
if( happyDay() ) {
Animal a("puppies");
body( a );
} else {
Animal a("toad");
body( a );
}
(Ab)Use placement new:
struct AnimalDtor {
void *m_a;
AnimalDtor(void *a) : m_a(a) {}
~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
};
char animal_buf[sizeof(Animal)]; // still stack allocated
if( happyDay() )
new (animal_buf) Animal("puppies");
else
new (animal_buf) Animal("toad");
AnimalDtor dtor(animal_buf); // make sure the dtor still gets called
Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
... // carry on
Since c++17, there is now an overhead-free way to do this: std::optional. The code in this case would be:
#include <optional>
std::optional<Animal> a;
if (happyDay()) {
a.emplace("puppies");
} else {
a.emplace("toads");
}
The best work around is to use pointer.
Animal a*;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
You can also use std::move:
class Ball {
private:
// This is initialized, but not as needed
sf::Sprite ball;
public:
Ball() {
texture.loadFromFile("ball.png");
// This is a local object, not the same as the class member.
sf::Sprite ball2(texture);
// move it
this->ball=std::move(ball2);
}
...
There is a way to do this without pointers/heap memory, this syntax is just a bit gibberish. Here is an example using std::string. I don't recommend doing this unless you really need the performance.
uint8_t object[sizeof(std::string)];
int main() {
if(true)
new(&object) std::string("Your arguments");
else
new(&object) std::string("Your other arguments");
(*(std::string*)(&object)).append("");
std::cout << (*(std::string*)(&object));
return 0;
}
The annoying part about this is you have to cast object to a string every time you want to use it:
(*(std::string*)(&object))
Yes, you can do do the following:
Animal a;
if( happyDay() )
a = Animal( "puppies" );
else
a = Animal( "toads" );
That will call the constructors properly.
EDIT: Forgot one thing...
When declaring a, you'll have to call a constructor still, whether it be a constructor that does nothing, or still initializes the values to whatever. This method therefore creates two objects, one at initialization and the one inside the if statement.
A better way would be to create an init() function of the class, such as:
Animal a;
if( happyDay() )
a.init( "puppies" );
else
a.init( "toads" );
This way would be more efficient.