The C++11 way of initializing data members from arguments - c++

Seeing as C++11 supports move semantics, when initializing data members from arguments, should we attempt to move the value instead of copying it?
Here's an example showing how I would approach this in pre-C++11:
struct foo {
std::vector<int> data;
explicit foo(const std::vector<int>& data)
: data(data)
{
}
};
Here, the copy constructor would be called.
In C++11, should we get into the habit of writing like this:
struct foo {
std::vector<int> data;
explicit foo(std::vector<int> data)
: data(std::move(data))
{
}
};
Here, the move constructor would be called... as well as the copy constructor if the argument passed is an lvalue, but the benefit is that if an rvalue was passed, the move constructor would be called instead of the copy one.
I'm wondering if there's something I'm missing.

My initial answer to your question was:
Don't copy data that you want to move. You can add a constructor using a rvalue reference, if performance is a problem:
explicit foo(std::vector<int>&& data)
: data(std::move(data)) // thanks to Kerrek SB
{
}
Not exactly matching your question, but reading
Rule-of-Three becomes Rule-of-Five with C++11?
seems to be useful.
Edit:
However, the accepted answer to
Passing/Moving parameters of a constructor in C++0x
seems to advocate your approach, especially with more than one parameter.
Otherwise there would be a combinatorial explosion of variants.

Passing by value in the copy constructor only helps when the argument is movable, otherwise you could end up with up to two copies (one for the argument passing, one for the member construction). So I'd say it's better to write a copy and a move constructor separately.
Passing by value makes sense for the assignment operator if you have a properly implemented swap function, though:
Foo & operator=(Foo other) { this->swap(std::move(other)); }
Now if other is moveable, Foo's move constructor comes in during argument construction, and if other is merely copyable, then the one necessary copy is made during argument construction, but in both cases you get to use the moving version of swap, which ought to be cheap. But this relies on the existence of a move constructor!
So note that out of "construction", "swap" and "assigment" you will have to implement two properly, and only the third can take advantage of the other two. Since swap should be no-throw, using the swap trick in the assigment operator is basically the only option.

Yes, you are doing it correctly. Any time you need a copy of a value, do it in the parameters by passing by value.
The following is correct:
struct foo {
std::vector<int> data;
explicit foo(std::vector<int> data)
: data(std::move(data))
{
}
};

You should stick with:
struct foo {
std::vector<int> data;
explicit foo(const std::vector<int>& data)
: data(data)
{
}
};
In which case "data" is only copied.
In the second case:
struct foo {
std::vector<int> data;
explicit foo(std::vector<int> data)
: data(std::move(data))
{
}
};
"data" is first copied and then moved. Which is more expensive than just copying. Remember moving is not free, even though it probably is alot cheaper than copying.
On the other hand you might consider adding the following (in addition to or instead of the first).
struct foo {
std::vector<int> data;
explicit foo(std::vector<int>&& data)
: data(std::move(data))
{
}
};
Where you know that "data" will not be used after the constructor call, and in which case you can just move it.

Related

Is there a way in C++ to deep copy only required variables in CCTOR? [duplicate]

I have a long class with a lot of data members. I want to write a copy constructor for it. But, if I write my own copy constructor, I lose access to the default copy constructor.
I just want to repair a few pointers in my own copy constructor. So I want to have a shallow copy of the object which can be done by the default copy constructor.
Is there a possibility to access the default copy constructor when I have my own copy constructor?
Wrap the things you don't want to change in a struct, and derive (privately) from it. In your copy constructor, simply invoke the copy constructor of your base class.
No you cannot have both default and your own copy c-tor.
But there are two workarounds with this problem:
1 Enclose your pointers in some class with defined copy semantics
Example:
class A {
public:
private:
int trivial1;
int trivial2;
...
SomePointer nontrivialMember;
};
class SomePointer {
public:
SomePointer(const SomePointer&); // here the non trivial part of A copy semantics
int* nonTrivialMember;
};
2 Enclose the trivial parameters in some trivial structure
Example:
class A {
public:
A(const A& o) : data(o.data) {
// non trivial part
}
private:
struct Data {
int trivial1;
int trivial2;
...
} data;
int* nontrivialMember;
};
I would always select the first solution.
[UPDATE]
There is also 3rd solution, very similar to my second, enclose your trivial part in privately inherited base class. I'd still prefer the 1st solution.
The simplest approach to this would be to wrap up the pointers into classes that will perform the 'repair' manually in their copy constructor, then you can happily use the default copy constructor.
No, there is no way to call the default copy constructor from an user defined copy constructor.
You can either use the default or your own, not both. If you want to choose different functionality for different objects you should just write a member function that handles that case.
void DeepCopy(MyClass* rhs);
For example.
You cannot access default copy ctor if you created your own - compiler just doesn't generate it. But ther is workaround - split you class into data structure and logic.
See example:
struct Data
{
int i;
std::string s;
Data(): i(), s() {}
};
class Code: private Data
{
public:
Code() {}
Code(const Code& rhs): Data(rhs) // Call default copy ctor
{
i = 42; // Your copy part
return *this;
}
};
My solution is a simple memcpy() instead of the impossible call to the implicit (compiler generated) copy constructor, as the example shown below:
Class Foo
{
public:
...
Foo (Foo & other) {
// copies trivial part (and non-trivial part with possible wrong values)
memcpy(this, &other, sizeof(Foo));
// your non-trivial part here, overwrites the wrong values (if any) above.
}
}
Yet the side-effect is that the memcpy() will also copy those non-trivial part, which is a waste. If the non-trivial part does not contain too much space, I will prefer my solution.
For example, a class like below wastes only 4 byte copy of the one pointer, assuming the size of a pointer is 4 bytes.
Class Bar
{
int x, y, z;
// memcpy() wastes these 4 bytes copy,
// since actual copy constructor wants a new string
string *s;
}
This worked for me... (C++11, don't know if it works on older std)
Not sure why it doesn't end up in an endless loop.
class Foo {
public:
Foo(const Foo &orig) {
*this = orig;
... exchange pointers, do own stuff
}

Efficient way to construct object with string member

Suppose I have a class ThisHasAStringMember. Assume it has a private member which is a string, and I want to efficiently get the string value, preferring a move over a copy where possible. Would the following two constructors accomplish that?
class ThisHasAStringMember
{
public:
// ctors
ThisHasAStringMember(const std::string str) : m_str(str) {}
ThisHasAStringMember(std::string &&str) : m_str(std::move(str)) {}
// getter (no setter)
std::string value() { return m_str; }
private:
std::string m_str;
}
Do I need the double ampersand before the str parameter in the second constructor?
Is this the right way to accomplish this?
At first I would notice that it's better to mark your constructors as explicit.
The next moment is that better change the first constructor in your solution to take const reference to avoid copying lvalue:
// ctors
ThisHasAStringMember(const std::string& str) : m_str(str) {}
ThisHasAStringMember(std::string &&str) : m_str(std::move(str)) {}
This approach is optimal from the performance point of view (you will have one copy constructor call for lvalue and one move constructor call for rvalue), however it's quite boring to implement each time two constructors in such case. And if you have N members - 2^N constructors.
There are few alternatives:
Signle constructor where you pass parameter just by value. Yes it was unefficient in C++98, but in C++11 when you create a full copy - that's an option.
ThisHasAStringMember(std::string str) : m_str(std::move(str)) {}
When lvalue is passed there will be one copy constructor call and one move constructor call. When rvalue is passed there will be two move constructor calls. Yes, you have one extra move constructor call in each of the cases. But it's often very cheap (or even can be optimized away by compiler) and the code is very simple.
Single constructor where you pass parameter by rvalue:
ThisHasAStringMember(std::string&& str) : m_str(std::move(str)) {}
If you pass lvalue you have to explicitely copy it first in a place of the call, e.g.
ThisHasAStringMember(copy(someStringVar)). (here copy is a simple template copying method). And you will still have one extra move constructor call for lvalues. For rvalues there will be no overhead. Personally I like this approach: all the places where the parameter is copied are explicit, you won't make occasional copies in a performance-critical places.
Make constructor template and use perfect forwarding:
template <typename String,
std::enable_if_t<std::is_constructible_v<std::string, String>>* = nullptr>
ThisHasAStringMember(String&& str) : m_str(std::forward<String>(str))
{}
You will have no overhead both for rvalues and lvalues, but you'll need to make your constructor template and define it in header in most of the cases.

implement move constructor & move assignment operator in c++98 for better performance

Can I simulate move constructor & move assignment operator functionality with copy constructor and assignment operator in C++98 to improve the performance whenever i know copy constructor & copy assignment will be called only for temporary object in the code OR i am inserting needle in my eyes?
I have taken two example's one is normal copy constructor & copy assignment operator and other one simulating move constructor & move assignment operator and pushing 10000 elements in the vector to call copy constructor.
Example(copy.cpp) of normal copy constructor & copy assignment operator
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class MemoryBlock
{
public:
// Simple constructor that initializes the resource.
explicit MemoryBlock(int length)
: _length(length)
, _data(new int[length])
{
}
// Destructor.
~MemoryBlock()
{
if (_data != NULL)
{
// Delete the resource.
delete[] _data;
}
}
//copy constructor.
MemoryBlock(const MemoryBlock& other): _length(other._length)
, _data(new int[other._length])
{
std::copy(other._data, other._data + _length, _data);
}
// copy assignment operator.
MemoryBlock& operator=(MemoryBlock& other)
{
//implementation of copy assignment
}
private:
int _length; // The length of the resource.
int* _data; // The resource.
};
int main()
{
// Create a vector object and add a few elements to it.
vector<MemoryBlock> v;
for(int i=0; i<10000;i++)
v.push_back(MemoryBlock(i));
// Insert a new element into the second position of the vector.
}
Example(move.cpp) of simulated move constructor & move assignment operator functionality with copy constructor & copy assignment operator
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class MemoryBlock
{
public:
// Simple constructor that initializes the resource.
explicit MemoryBlock(int length=0)
: _length(length)
, _data(new int[length])
{
}
// Destructor.
~MemoryBlock()
{
if (_data != NULL)
{
// Delete the resource.
delete[] _data;
}
}
// Move constructor.
MemoryBlock(const MemoryBlock& other)
{
// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;
// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
(const_cast<MemoryBlock&>(other))._data = NULL;
//other._data=NULL;
}
// Move assignment operator.
MemoryBlock& operator=(const MemoryBlock& other)
{
//Implementation of move constructor
return *this;
}
private:
int _length; // The length of the resource.
int* _data; // The resource.
};
int main()
{
// Create a vector object and add a few elements to it.
vector<MemoryBlock> v;
for(int i=0; i<10000;i++)
v.push_back(MemoryBlock(i));
// Insert a new element into the second position of the vector.
}
I observed performance is improved with some cost:
$ g++ copy.cpp -o copy
$ time ./copy
real 0m0.155s
user 0m0.069s
sys 0m0.085s
$ g++ move.cpp -o move
$ time ./move
real 0m0.023s
user 0m0.013s
sys 0m0.009s
We can observe that performance is increased with some cost.
Has any pitfall to implement move constructor and move assignment
operator simulated functionality in c++98, even I am sure that copy
constructor & assignment only call when temporary objects are
created?
Has there any other way/technique to implement the move constructor
and assignment operator in c++98?
You will not be able to have the language understand R-values in the same way that C++11 and above will, but you can still approximate the behavior of move semantics by creating a custom "R-Value" type to simulate ownership transferring.
The Approach
"Move semantics" is really just destructively editing/stealing the contents from a reference to an object, in a form that is idiomatic. This is contrary to copying from immutable views to an object. The idiomatic approach introduced at the language level in C++11 and above is presented to us as an overload set, using l-values for copies (const T&), and (mutable) r-values for moves (T&&).
Although the language provides deeper hooks in the way that lifetimes are handled with r-value references, we can absolutely simulate the move-semantics in C++98 by creating an rvalue-like type, but it will have a few limitations. All we need is a way to create an overload set that can disambiguate the concept of copying, from the concept of moving.
Overload sets are nothing new to C++, and this is something that can be accomplished by a thin wrapper type that allows disambiguating overloads using tag-based dispatch.
For example:
// A type that pretends to be an r-value reference
template <typename T>
class rvalue {
public:
explicit rvalue(T& ref)
: _ref(&ref)
{
}
T& get() const {
return *_ref;
}
operator T&() const {
return *_ref;
}
private:
T* _ref;
};
// returns something that pretends to be an R-value reference
template <typename T>
rvalue<T> move(T& v)
{
return rvalue<T>(v);
}
We won't be able behave exactly like a reference by accessing members by the . operator, since that functionality does not exist in C++ -- hence having get() to get the reference. But we can signal a means that becomes idiomatic in the codebase to destructively alter types.
The rvalue type can be more creative based on whatever your needs are as well -- I just kept it simple for brevity. It might be worthwhile to add operator-> to at least have a way to directly access members.
I have left out T&& -> const T&& conversion, T&& to U&& conversion (where U is a base of T), and T&& reference collapsing to T&. These things can be introduced by modifying rvalue with implicit conversion operators/constructors (but might require some light-SFINAE). However, I have found this rarely necessary outside of generic programming. For pure/basic "move-semantics", this is effectively sufficient.
Integrating it all together
Integrating this "rvalue" type is as simple as adding an overload for rvalue<T> where T is the type being "moved from". With your example above, it just requires adding a constructor / move assignment operator:
// Move constructor.
MemoryBlock(rvalue<MemoryBlock> other)
: _length(other.get()._length),
_data(other.get()._data)
{
other.get()._data = NULL;
}
MoveBlock& operator=(rvalue<MemoryBlock> other)
{
// same idea
}
This allows you to keep copy constructors idiomatic, and simulate "move" constructors.
The use can now become:
MemoryBlock mb(42);
MemoryBlock other = move(mb); // 'move' constructor -- no copy is performed
Here's a working example on compiler explorer that compares the copy vs move assemblies.
Limitations
No PR-values to rvalue conversion
The one notable limitation of this approach, is that you cannot do PR-value to R-value conversions that would occur in C++11 or above, like:
MemoryBlock makeMemoryBlock(); // Produces a 'PR-value'
...
// Would be a move in C++11 (if not elided), but would be a copy here
MemoryBlock other = makeMemoryBlock();
As far as I am aware, this cannot be replicated without language support.
No auto-generated move-constructors/assignment
Unlike C++11, there will be no auto-generated move constructors or assignment operators -- so this becomes a manual effort for types that you want to add "move" support to.
This is worth pointing out, since copy constructors and assignment operators come for free in some cases, whereas move becomes a manual effort.
An rvalue is not an L-value reference
In C++11, a named R-value reference is an l-value reference. This is why you see code like:
void accept(T&& x)
{
pass_to_something_else(std::move(x));
}
This named r-value to l-value conversion cannot be modeled without compiler support. This means that an rvalue reference will always behave like an R-value reference. E.g.:
void accept(rvalue<T> x)
{
pass_to_something_else(x); // still behaves like a 'move'
}
Conclusion
So in short, you won't be able to have full language support for things like PR-values. But you can, at least, implement a means of allowing efficient moving of the contents from one type to another with a "best-effort" attempt. If this gets adopted unanimously in a codebase, it can become just as idiomatic as proper move-semantics in C++11 and above.
In my opinion, this "best-effort" is worth it despite the limitations listed above, since you can still transfer ownership more efficiently in an idiomatic manner.
Note: I do not recommend overloading both T& and const T& to attempt "move-semantics". The big issue here is that it can unintentionally become destructive with simple code, like:
SomeType x; // not-const!
SomeType y = x; // x was moved?
This can cause buggy behavior in code, and is not easily visible. Using a wrapper approach at least makes this destruction much more explicit

Should a type be move-only, just because copying may be expensive?

I have a type that is copyable, but may be expensive to copy. I have implemented the move constructor and move assignment. But I have performance issues where folks forget to call move() when passing by value.
Is it good C++11 style to remove the copy constructor, and instead provide an explicit copy() method for the rare cases when a copy is actually desired? This is idiomatic in other languages (Ruby, JavaScript) but I don't know of anything in the C++ standard library that prohibits copy purely for performance. For instance, std::vector<> is copyable, while std::unique_ptr<> and std::thread are non copyable for other reasons.
Should a type be move-only, just because copying may be expensive?
No. If the semantics of your type is such that copying it is conceptually meaningful, then the correct way to make copying available is to implement a copy constructor, and give the user a chance to adopt standard syntax for invoking it:
T a;
T a = b;
If people will forget to move from objects they don't want to use anymore... Well, that's their bad:
T c = std::move(a); // I'm doing it right (if I no longer need object a);
T d = b; // If I don't need b anymore, I'm doing it wrong.
And if (for any reason) for some functions of yours it is always desirable that the caller provides an object from which it is possible to move, then let the function accept an rvalue reference:
void foo(my_class&& obj);
my_class a;
foo(a); // ERROR!
foo(std::move(a)); // OK
I would treat the class as non-copyable in signature if copy is sufficiently expensive. Semantically things are copyable only if you want them to be, and an expensive copy is a decent reason to decide "no, not copyable".
The ability for something to be copied does not mean it need be implemented in a type that is copyable. The implementer of that type gets to decide if it should be semantically copyable.
I wouldn't call the operation that produced an expensive copy "copy", but rather "clone" or "duplicate".
For a way you might do this:
#include <utility>
template<typename T>
struct DoCopy {
T const& t;
DoCopy( T const& t_ ):t(t_) {}
};
template<typename T>
DoCopy<T> do_copy( T const& t ) {
return t;
}
struct Foo {
struct ExpensiveToCopy {
int _[100000000];
};
ExpensiveToCopy* data;
Foo():data(new ExpensiveToCopy()) {}
~Foo(){ delete data; }
Foo(Foo&& o):data(o.data) { o.data = nullptr; }
Foo& operator=(Foo&& o) { data=o.data; o.data=nullptr; return *this; }
Foo& operator=(DoCopy<Foo> o) {
delete data;
if (o.t.data) {
data=new ExpensiveToCopy(*o.t.data);
} else {
data=new ExpensiveToCopy();
}
return *this;
}
Foo( DoCopy<Foo> cp ):data(cp.t.data?new ExpensiveToCopy( *cp.t.data ):new ExpensiveToCopy() ) {};
};
int main() {
Foo one;
// Foo two = one; // illegal
Foo three = std::move(one); // legal
Foo four;
Foo five = do_copy(three);
four = std::move(three);
five = do_copy(four);
}
This is somewhat similar to the ways you could have written std::move like semantics prior to the existence of rvalue references, with similar downsides to such techniques, namely that the language itself has no idea what shenanigans you are up to.
It has the advantage that the syntax of the above do_copy is similar to the syntax of std::move, and it allows you to use traditional expressions without having to create trivial instances of Foo then construct a copy of another variable etc.
If the situations where we want to treat it as copyable are common (if to be avoided), I'd write a copy-wrapper around the class that knows about the duplicate method.
No. If the type is copyable then the type is copyable. This means its copy constructor is available and works. It doesn't mean there's some member function whose name looks like the characters c, o, p and y in sequence, that does "sort of nearly a similar thing".

C++11 / VS2010 : Returning containers of uncopyable but movable objects

Consider the following code:
#include <vector>
#include <boost/noncopyable.hpp>
struct A : private boost::noncopyable
{
A(int num, const std::string& name)
: num(num),
name(name)
{
}
A(A&& other)
: num(other.num),
name(std::move(other.name))
{
}
int num;
std::string name;
};
std::vector<A> getVec()
{
std::vector<A> vec;
vec.emplace_back(A(3, "foo"));
// vec.emplace_back(3, "foo"); not available yet in VS10?
return vec; // error, copy ctor inaccessible
}
int main ( int argc, char* argv[] )
{
// should call std::vector::vector(std::vector&& other)
std::vector<A> vec = getVec();
return 0;
}
This does not compile under VS2010 because obviously A is noncopyable and thus std::vector<A> cannot be copied. Accordingly I cannot return a std::vector<A> from a function.
However it doesn't feel right to me that this sort of thing is not possible considering the concept of RVO. If Return Value Optimization was applied here, copy construction could be omitted and the call to getVec() would be valid.
So what would be the proper way to do this? Is this possible at all in VS2010 / C++11?
If return vec; does not compile, VS2010 does not support move semantics fully yet. Normally, automatic variables are moved implicitly if returned from a function. Use return std::move(vec); as an interim workaround, and make a note in your head to get rid of the std::move in the future.
A full explanation can be found in this FAQ answer under the headline "Moving out of functions".
Also, your two-argument constructor makes a copy of the string argument which is passed by reference-to-const. I would suggest taking the argument by value instead and moving it into the member:
A(int num, std::string name) : num(num), name(std::move(name)) { }
This way, you minimize the number of necessary copies. See Want Speed? Pass by Value for details.
Also, since your move constructor doesn't do anything special, you can default it:
A(A&& other) = default;
This makes it more robust in the face of changes. Bugs seldomly hide in the code you don't write :)
However it doesn't feel right to me that this sort of thing is not possible considering the concept of RVO.
Elision, the general term for stuff like named return value optimization, is an optimization. It is not required. The specification allows it, but doesn't force any implementation to do it even when it is allowed to.
As such, to enforce consistency between compilers that allow elision and those that don't, if elision is allowed by an operation, the compiler must still verify that the copy/move being elided would be possible given the current state of the code. So if a copy/move constructor is not accessible, the operation fails even if the compiler won't actually call it.
In this case, Visual Studio 2010 seems to be kind of confused in this regard. It does recognize that return vec; should move from vec. However, it seems that VS2010's std::vector implementation needs a move assignment operator to move; without one, it will attempt to copy.