My head hurts: I've read so many blogs about C++11x's move semantics that my brain's gone mushy, so please can someone give me a short-but-sweet guide on how to make the following code work efficiently? Given a class Foo, I want to be able to write functions that return Foo objects in different states (sometimes called source functions), and to do this as efficiently as possible.
class Foo {
// Some methods and members
};
Foo getFirstFoo() {
Foo foo;
// Do some things to foo
return foo;
}
Foo getSecondFoo() {
Foo foo;
// Do some different things to foo
return foo;
}
int main() {
Foo f = getFoo();
// use f ...
f = getSecondFoo();
// use f ...
return 0;
}
I don't want to modify Foo much, and the idea is to allow all sorts of Foo objects to be created through a variety of non-member source functions, so adding ever more constructors would be missing the point.
In C++03 my options would be to wrap the returned object in an auto_ptr (a big downside being that the recipient code needs to know to handle a smart pointer), or to cross my fingers and hope that some sort of optimization might take place (likely for the first line in main, less so for the second). C++11x seems to provide something better through move semantics, but how would I take advantage of these? So I need to change the way objects are returns in the source functions, or add some move constructor to Foo, or both?
This is already optimal1, provided that move constructors are generated2:
class Foo {
public:
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
};
Returned values are rvalue references by default.
1 Well.... provided that your class Foo benefits from move construction at all. Remember, move is an optimization of copy. Some copies cannot be improved! E.g, unsuited:
struct Foo { int data; };
struct Foo2 { int data[5<<10]; };
well suited:
struct Foo3 { std::vector<std::string> data; };
See Move semantics - what it's all about? for a more general background on things like this.
2 Not all compilers do support that yet (even if they do implement rvalue references), so you might have to write the
move constructor
move assignment
Related
I have a class that stores a large std::map. My understanding is that the idiomatic way to do this is:
class Foo {
public:
Foo(/* Note: passed by value */ std::map<Bar, Baz> large_map) : large_map_(std::move(large_map)) {}
private:
std::map<Bar, Baz> large_map_;
};
int main() {
std::map<Bar, Baz> large_map;
// Work hard to initialize large_map.
Foo foo = Foo(std::move(large_map));
}
This transfers the ownership of large_map from main, to the constructor arg and then to Foo's member. The problem with this is that the code is hard to use properly and I discovered that someone somewhere created a Foo and forgot to move the map into the ctor:
void deep_dark_hidden_code() {
std::map<Bar, Baz> large_map;
// Work hard to initialize large_map.
Foo foo = Foo(large_map); // Whoops! The author of this code forgot to std::move
}
I am looking for a way to write Foo which protects against such mistakes. My first thought was to use unique_ptr
class Foo {
public:
Foo(std::unique_ptr<std::map<Bar, Baz>> large_map_ptr) : large_map_(std::move(*large_map_ptr)) {}
private:
std::map<Bar, Baz> large_map_;
};
int main() {
std::unique_ptr<std::map<Bar, Baz>> large_map_ptr = new std::map<Bar, Baz>;
// Work hard to initialize large_map_ptr.
Foo foo = Foo(std::move(large_map_ptr));
}
This code is essentially using unique_ptr as a hack to erase the copy constructor of std::map. My question is whether there is a more explicit way to do this. Some magic template make_uncopyable like:
class Foo {
public:
Foo(make_uncopyable<std::map<Bar, Baz>> large_map) : large_map_(std::move(large_map)) {}
private:
std::map<Bar, Baz> large_map_;
};
The desired effect is to leave the code in my main intact but prevent the code in deep_dark_hidden_code from compiling.
The title appears to be a slight misnomer here (or is at least at odds with the contents with your question):
(At least in the example given), you do not want to remove the copy constructor i.e. Foo::Foo(const Foo& other), but rather prevent invokation of Foo's constructor with a non-movable argument.
As Mestkon pointed out (all credit to them - if they want to post it as an answer, just give me a yell and I'll remove mine), you could change Foo's constructor to require a std::map<Bar, Baz>&& large_map i.e.
Foo(std::map<Bar, Baz>&& large_map) : large_map_(std::move(large_map)) {}
A test at Godbolt confirms that the compiler will refuse to accept the Foo foo = Foo(large_map); in the deep_dark_hidden_code()., demanding the argument to be movable (as desired). This this might still run the risk of others "fixing" their code by simply slapping a std::move() around their large_map... and then attempting to continue using it after constructing Foo with it.
If you want really want to prevent the invokation of the copy constructor (here std::map), things become rather difficult, as you cannot change the the definition std::map to erase its copy constructor. I don't feel I have a good answer to this.
This question asks for a clean way of implementing a static factory method in C++, and this answer describes a clear way to do so. Return Value Optimization would save us from making an unnecesary copy of Object, thus making this way of creating an Object as efficient as directly invoking a constructor. The overhead of copying i to id inside a private constructor is negligible because it's a small int.
However, the question and answer don't cover a more complex case when Object contains an instance variable that is an instance of class Foo (that requires complex initialization logic) rather than a small primitive type. Suppose I want to construct Foo using the arguments passed to Object. A solution using a constructor would look something like:
class Object {
Foo foo;
public:
Object(const FooArg& fooArg) {
// Create foo using fooArg here
foo = ...
}
}
An alternative with a static factory method analogous to the quoted answer would be, as it appears to me:
class Object {
Foo foo;
explicit Object(const Foo& foo_):
foo(foo_)
{
}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
Foo foo = ...
return Object(foo);
}
}
Here, the overhead of copying foo_ to foo is no longer necessarily negligible, since Foo can be an arbitrarily complex class. Moreover, as far as I understand (C++ newbie here so I may be wrong), this code implicitly requires for a copy constructor to be defined for Foo.
What would be a similarly clean but also efficient way of implementing this pattern in this case?
To anticipate possible questions about why this is relevant, I consider having constructors with logic more complicated than just copying the arguments to be an anti-pattern. I expect the constructor to:
be guaranteed to work and not throw exceptions,
and not do heavy calculations under the hood.
Thus, I prefer to put complex initialization logic into static methods. Moreover, this approach provides additional benefits such as overloading by static factory method name even when the input argument types are the same, and the possibility of clearly stating what is being done inside in the name of the method.
Thanks to move constructor, you might do:
class Object {
Foo foo;
explicit Object(Foo&& foo_) : foo(std::move(foo_)) {}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
Foo foo = ...
return Object(std::move(foo));
}
};
If Foo is not movable, wrapping it in smart pointer is a possibility:
class Object {
std::unique_ptr<Foo> foo;
explicit Object(std::unique_ptr<Foo>&& foo_) : foo(std::move(foo_)) {}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
std::unique_ptr<Foo> foo = ...
return Object(std::move(foo));
}
};
What is wrong with initializing the instance in the constructor directly from the arguments needed to do so?
class Object
{
Foo foo; // or const Foo foo, disallowing assignment
public:
explicit Object(FooCtorArgs const&fooArg,
const AdditionalData*data = nullptr)
: foo(fooArg) // construct instance foo directly from args
{
foo.post_construction(data); // optional; doesn't work with const foo
}
static Object FromFooArg(FooCtorArgs const&fooArg,
const AdditionalData*data = nullptr)
{
return Object{fooArg,data}; // copy avoided by return value optimization
}
};
AFAICT, there is no need to copy/move anything, even if you need to adjust foo post construction.
Consider the following, simplified facade pattern:
class Foo {
public:
int times;
int eval(const int val) { return val*times; }
};
class Bar {
Foo foo;
public:
Bar(const Foo& f) : foo(f) {}
double eval(const double val) { return val * foo.times; }
};
Obviously, an instance of Bar is only required to evaluate a special (i.e. double-valued) interpretation of Foo's eval() method. A Bar won't have any other members except the foo it forwards to.
For safety reasons I have not used a const reference or a pointer inside Bar (I just don't know yet if at some point a Bar instance might escape from a stack frame, so resource management is important).
My question here is two fold:
Can the C++ compiler possibly detect that Bar is merely a facade and
"inline" the member access?
Is there a (safe) way to prevent copying
of the passed object?
On some platforms (gcc/clang) you can force inlining with the attribute always_inline or emit warnings should a function not be inlined.
No, if you don't want to copy, you need to guarantee the life-time of the object elsewhere. If you consider this to be unsafe, don't do it. What you can do is move an object. This avoids copies and life-time issues, but might not be possible with your compiler.
For example:
struct Bar {
// Only accept rvalues of Foo
explicit Bar(Foo&& f) : f(std::move(f)) {}
Foo f;
};
1- Yes, the compiler will most probably inline the function [It depends on compiler).
2- Always stick to RAII. In C++3, Foo object foo shall be either member variable (as you did), or managed pointer (copied at copy constructor and assignment operator and deleted at destructor). In C++11 you can use right value reference.
NOTE: This example is not a facade!
This may be a silly question, but still I'm a bit curious...
Recently I was working on one of my former colleague projects, and I've noticed that he really loved to use something like this:
int foo(7);
instead of:
int foo = 7;
Is this a normal/good way to do in C++ language?
Is there some kind of benefits to it? (Or is this just some silly programming style that he was into..?)
This really reminds me a bit of a good way how class member variables can be assigned in the class constructor... something like this:
class MyClass
{
public:
MyClass(int foo) : mFoo(foo)
{ }
private:
int mFoo;
};
instead of this:
class MyClass
{
public:
MyClass(int foo)
{
mFoo = foo;
}
private:
int mFoo;
};
For basic types there's no difference. Use whichever is consistent with the existing code and looks more natural to you.
Otherwise,
A a(x);
performs direct initialization, and
A a = x;
performs copy initialization.
The second part is a member initializer list, there's a bunch of Q&As about it on StackOverflow.
Both are valid. For builtin types they do the same thing; for class types there is a subtle difference.
MyClass m(7); // uses MyClass(int)
MyClass n = 3; // uses MyClass(int) to create a temporary object,
// then uses MyClass(const MyClass&) to copy the
// temporary object into n
The obvious implication is that if MyClass has no copy constructor, or it has one but it isn't accessible, the attempted construction fails. If the construction would succeed, the compiler is allowed to skip the copy constructor and use MyClass(int) directly.
All the answers above are correct. Just add that to it that C++11 supports another way, a generic one as they say to initialize variables.
int a = {2} ;
or
int a {2} ;
Several other good answers point out the difference between constructing "in place" (ClassType v(<constructor args>)) and creating a temporary object and using the copy constructor to copy it (ClassType v = <constructor arg>). Two additional points need to be made, I think. First, the second form obviously has only a single argument, so if your constructor takes more than one argument, you should prefer the first form (yes, there are ways around that, but I think the direct construction is more concise and readable - but, as has been pointed out, that's a personal preferance).
Secondly, the form you use matters if your copy constructor does something significantly different than your standard constructor. This won't be the case most of the time, and some will argue that it's a bad idea to do so, but the language does allow for this to be the case (all surprises you end up dealing with because of it, though, are your own fault).
It's a C++ style of initializing variables - C++ added it for fundamental types so the same form could be used for fundamental and user-defined types. this can be very important for template code that's intended to be instantiated for either kind of type.
Whether you like to use it for normal initialization of fundamental types is a style preference.
Note that C++11 also adds the uniform initialization syntax which allows the same style of initialization to be used for all types - even aggregates like POD structs and arrays (though user defined types may need to have a new type of constructor that takes an initialization list to allow the uniform syntax to be used with them).
Yours is not a silly question at all as things are not as simple as they may seem. Suppose you have:
class A {
public:
A() {}
};
and
class B {
public:
class B(A const &) {}
};
Writing
B b = B(A());
Requires that B's copy constructor be accessible. Writing
B b = A();
Requires also that B's converting constructor B(A const &) be not declared explicit. On the other hand if you write
A a;
B b(a);
all is well, but if you write
B b(A());
This is interpreted by the compiler as the declaration of a function b that takes a nameless argument which is a parameterless function returning A, resulting in mysterious bugs. This is known as C++'s most vexing parse.
I prefer using the parenthetical style...though I always use a space to distinguish from function or method calls, on which I don't use a space:
int foo (7); // initialization
myVector.push_back(7); // method call
One of my reasons for preferring using this across the board for initialization is because it helps remind people that it is not an assignment. Hence overloads to the assignment operator will not apply:
#include <iostream>
class Bar {
private:
int value;
public:
Bar (int value) : value (value) {
std::cout << "code path A" << "\n";
}
Bar& operator=(int right) {
value = right;
std::cout << "code path B" << "\n";
return *this;
}
};
int main() {
Bar b = 7;
b = 7;
return 0;
}
The output is:
code path A
code path B
It feels like the presence of the equals sign obscures the difference. Even if it's "common knowledge" I like to make initialization look notably different than assignment, since we are able to do so.
It's just the syntax for initialization of something :-
SomeClass data(12, 134);
That looks reasonable, but
int data(123);
Looks strange but they are the same syntax.
I'm looking for a way to define a "base" constructor, that will initialize values using defaults, and then extend that base into a number of specialized constructors.
The pseudocode of what I want might look like:
class Foo{
private:
int val;
/* ... */
public:
// Base constructor
Foo(){ /*...*/ } // This provides basic initialization of members
// Named constructors
static Foo fromString(string s){
Foo f; // Call base constructor
f.val = s.length(); // Customize base object
return f; // Return customized object
}
static Foo fromInt(int v){
Foo f;
f.val = v;
return f;
}
}
At first, I thought about extending the lifetime of the temporary f, but the const declaration prevents me from editing its members. So it seems this is out.
Then I tried the "named constructor" approach (which is shown above). However, I had to modify the example to create the object first, then modify it, then return it. This seems to work, but I'm reasonably confident that it is just a coincidence since f is a temporary and goes out of scope at the end of the function.
I've also considered using something like auto_ptrs, but then I'm working with both Foo objects as well as auto_ptrs to Foo, and this makes the rest of the code "care" whether objects are created via the base constructor (in which case it would be an object) or via one of the extended constructors (in which case it would be a pointer).
If it helps, in Python, I would use something like this:
class Foo(object):
def __init__(self):
/* Basic initialization */
#classmethod
def fromString(cls, s):
f = Foo() #†
f.val = len(s)
return f
Lastly, there are two reasons I want to do it this way:
Code reuse, I would like to move the common initialization out of each of the constructors and into one. I realize I can do this via an init()-type private method called by each constructor, but I just wanted to mention this.
Clarity and resolve ambiguity. Much like the motivation for the named constructor example, parameter types by themselves aren't enough to determine which ctor should be used. Additionally, the fromSomething syntax provides excellent clarity.
Forgive me if there is a simple solution, my work has shifted from c++ to Java/Python for the past few years so I'm a bit rusty.
This is perfectly valid:
static Foo fromInt(int v){
Foo f;
f.val = v;
return f;
}
This invokes Foo's copy constructor when you return f(probably the compiler applies return value optimization, so no copies are made). f goes out of scope, but the return value is just a copy of it, so this is totally valid, it's not just "a coincidence" that it's working.
So if your worries about using the named constructor approach is just that you don't really know if it works, go ahead with it, it works perfectly.
In C++11, you can call other constructors from constructors:
struct X{
X() : ... { ... }
X(int i) : X() { ... }
X(std::string s) : X() { ... }
};
For C++03, the named constructor approach is likely the best and perfectly reasonable, IMHO.
Why not:
class Foo{
private:
int val;
void Init(int v = <some default value>/*What ever here *));
/* ... */
public:
// Base constructor
Foo(){ Init(); } // This provides basic initialization of
Foo(string &s) { Init(s.length); };
Foo(int v) { Init(v); };
};
Seems simpler.