Returning object from function - c++

I am really confused now on how and which method to use to return object from a function. I want some feedback on the solutions for the given requirements.
Scenario A:
The returned object is to be stored in a variable which need not be modified during its lifetime. Thus,
const Foo SomeClass::GetFoo() {
return Foo();
}
invoked as:
someMethod() {
const Foo& l_Foo = someClassPInstance->GetFoo();
//...
}
Scneraio B:
The returned object is to be stored in a variable which will be modified during its lifetime. Thus,
void SomeClass::GetFoo(Foo& a_Foo_ref) {
a_Foo_ref = Foo();
}
invoked as:
someMethod() {
Foo l_Foo;
someClassPInstance->GetFoo(l_Foo);
//...
}
I have one question here: Lets say that Foo cannot have a default constructor. Then how would you deal with that in this situation, since we cant write this anymore:
Foo l_Foo
Scenario C:
Foo SomeClass::GetFoo() {
return Foo();
}
invoked as:
someMethod() {
Foo l_Foo = someClassPInstance->GetFoo();
//...
}
I think this is not the recommended approach since it would incur constructing extra temporaries.
What do you think ? Also, do you recommend a better way to handle this instead ?

First, let's look into the things that come into play here:
(a) Extending lifetime of a temporary when it's used to initialize a reference - I learnt about it in this publication by Andrei Anexandrescu. Again, it feels weird but useful:
class Foo { ... }
Foo GetFoo() { return Foo(); } // returning temporary
void UseGetFoo()
{
Foo const & foo = GetFoo();
// ... rock'n'roll ...
foo.StillHere();
}
The rule says that when a reference is initialized with a temporary, the temporary's lifetime is extended until the reference goes out of scope. (this reply quotes the canon)
(b) Return Value Optimization - (wikipedia) - the two copies local --> return value --> local may be omitted under circumstances. That's a surprising rule, as it allows the compiler to change the observable behavior, but useful.
There you have it. C++ - weird but useful.
So looking at your scenarios
Scenario A: you are returning a temporary, and bind it to a reference - the temporary's lifetime is extended to the lifetime of l_Foo.
Note that this wouldn't work if GetFoo would return a reference rather than a temporary.
Scenario B: Works, except that it forces a Construct-Construct-Copy-Cycle (which may be much more expensive than single construct), and the problem you mention about requiring a default constructor.
I wouldn't use that pattern to create a object - only to mutate an existing one.
Scenario C: The copies of temporaries can be omitted by the compiler (as of RVO rule). There is unfortunately no guarantee - but modern compilers do implement RVO.
Rvalue references in C++ 0x allows Foo to implement a resource pilfering constructor that not only guarantees supression of the copies, but comes in handy in other scenarios as well.
(I doubt that there's a compiler that implements rvalue references but not RVO. However there are scenarios where RVO can't kick in.)
A question like this requires mentioning smart pointers, such as shared_ptr and unique_ptr (the latter being a "safe" auto_ptr). They are also in C++ 0x. They provide an alternate pattern for functions creating objects.

Out of the three scenarios, number 3 is the ideomatic method, and the one you should probably use. You won't be paying for extra copies because the compiler is free to use copy elision to avoid the copy if possible.
Secnario A is wrong. You end up with a reference to a temporary which is destroyed when the statement containing the function call finishes. Okay, Scenario A is not wrong, but you should still use Scenario C.
Secnario B works just fine, but:
Lets say that Foo cannot have a default constructor. Then how would you deal with that in this situation, since we cant write this anymore: Foo l_Foo.
Foo has to have a default constructor. Even if you don't give it one, the compiler must for you. Assuming you declare a private constructor, there's no way you can use this calling method. You need to either make Foo default constructable or use Secnario C.

Related

What problems are solved by holding a Temporary using `const T &`?

Like, if I write code that looks like the following:
const int & const_value = 10;
What advantage am I gaining over code that would instead look like this:
int value = 10;
or
const int const_value = 10;
Even for a more complicated example, like
const enterprise::complicated_class_which_takes_time_to_construct & obj = factory.create_instance();
Thanks to copy elision, both of the following code snippets shouldn't be significantly faster or less memory consuming.
enterprise::complicated_class_which_takes_time_to_construct obj = factory.create_instance();
or
const enterprise::complicated_class_which_takes_time_to_construct obj = factory.create_instance();
Is there something I'm missing that explains the use of this construct, or a hidden benefit I'm not accounting for?
Edit:
The answer provided by #nwp supplied the example of a factory method that looks like the following:
using cc = enterprise::complicated_class_which_takes_time_to_construct;
struct Factory{
const cc &create_instance(){
static const cc instance;
return instance;
}
} factory;
While this is a good example of why you'd need the exact const reference construct in general, it doesn't answer why it would be needed for dealing with temporaries, or why this particular construct would be better than just seating the temporary in a proper stack-allocated object, which the compiler should still be able to copy-elide in normal situations.
Imagine the factory is "clever" and does something like
using cc = enterprise::complicated_class_which_takes_time_to_construct;
struct Factory{
const cc &create_instance(){
static const cc instance;
return instance;
}
} factory;
and further assume cc is not copyable then the const & version works while the other 2 don't. This is fairly common for classes that implement a cache and keep a local map of objects and you get a reference to the object inside the map.
Edit:
It is possible a coding guideline would say Take return values from functions by const &, because that works universally with values and references.
cc foo();
cc &foo();
const cc &foo();
If you use const cc &var = foo(); it will work without an unnecessary copy in all the cases. Sometimes you get a temporary, sometimes you don't, but the code always does the right thing, freeing you to change the implementation and to not having to care about how the function you use returns its return-value. There is still the issue of having a const in there, so it is not the superior notation in all cases, but it is a viable design choice.
There's one "pathological" case that comes to mind: non-copyable and non-movable objects. Such an object cannot be stored by value, so holding it by a reference is your only chance:
#include <iostream>
struct Immovable
{
Immovable(int i) : i(i) {}
Immovable(const Immovable&) = delete;
Immovable(Immovable&&) = delete;
const int i;
};
Immovable factory()
{
return {42};
}
int main()
{
const Immovable &imm = factory();
std::cout << imm.i;
}
[Live example]
On a less contrived note, you dismissed the "heavy object" optimisation by citing copy elision. Note, however, that copy elision is optional. You can never guarantee that the compiler will do it. Storing the temporary in a const &, on the contrary, guarantees that no copying or moving will happen.
The rationale for the lifetime extension rule is known ¹(because Bjarne Stroustrup, the language creator, said so) to be to have uniform simple rules. In particular, the lifetime of a temporary used as actual argument in a function call, is extended to the end of the full-expression, covering the lifetime of any reference that it's bound to. And the rule for local reference to const, or local rvalue reference, makes that aspect of the behavior the same.
In C++03 one practical use case, as far as I know ²invented by Petru Marginean, was to create a local object of an unknown automatically deduced type, like this:
Base const& o = foo( arg1, arg2, arg3 );
This works when Base is an accessible base class of any possible foo result type, because the lifetime extension mechanism does not slice: it extends the lifetime of the full temporary object. When foo returns a T it's a complete T object that has its lifetime extended. The compiler knows T even though the programmer may not necessarily know T.
Of course, in C++11 and later one can instead, generally, use auto:
auto const o = foo( arg1, arg2, arg3 );
With return value optimization and/or moving this will be just as efficient as Marginean's trick, and it's more clear and simple.
However, when the type T is non-movable and non-copyable, then binding to a reference with lifetime extension of the temporary, appears to be the only way to hold on to it, which is a second use case.
Now, surprise?, the type T of the full temporary object needs not be derived from the statically known type. It's enough that compiler knows that you're holding a reference to a part of the temporary. Whether that part is a base class sub-object, or some other sub-object, doesn't matter, so you can do:
auto const& part = foo( arg1, arg2, arg3 ).a_part;
Which is a third use case, which is only about not introducing an otherwise never used name for the complete object, keeping the code simple.
Standardese about the hold-on-to-a-part (and thus the whole object) case:
C++15 §12.2/5 [class.temporary]
” The temporary to which the reference is
bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except …
The exceptions include that a temporary used as actual argument in a function call, persists till the end of the full-expression, i.e. a bit longer than any formal argument reference that it's bound to.
¹ In an exchange with me in the Usenet group comp.lang.c++.
² In the C++03 implementation of the ScopeGuard class, which was invented by Petru. In C++11 a ScopeGuard can be trivially implemented using std::function and auto in the client code's dceclaration.

Use a temporary as default argument in constructor

In C++, we can assign an object to a non-const reference. So this works:
Foo &foo = Foo();
But, C++ doesn't allow a temporary to be assigned to a non-const reference. So this is not allowed:
Bar::Bar(Foo &foo = Foo()) {}
But this is allowed
Bar::Bar(const Foo &foo = Foo()) {}
I have three questions here:
What is the scope of foo in the last case? Does it live even after the constructor is exited. From what I read, the lifetime of a temporary is modified if it is assigned to a const reference, in which case it takes up the lifetime of the reference is it assigned to. What is the lifetime of the default argument, in this case foo?
I tried the second example in MSVC and it didn't complain. I also noticed that the lifetime of the temporary was still extended. So I could use foo after the constructor exited. What is that about?
My scenario demands the default argument to constructor in this manner and I will need to modify the argument in the constructor (so I cannot make it const). And I also need to use foo after the constructor has exited. What is the best design to cater to this scenario?
Thanks in advance.
What is the scope of foo in the last case?
foo is a constructor (same applies to regular functions too) argument, so its lifetime ends when the full expression containing the call to the constructor ends. Thanks aschepler!
What is the lifetime of the default argument, in this case foo?
You extended the lifetime of the default argument by binding it to Foo const& foo, so its lifetime will match that of the reference it's bound to, i.e. until the constructor body exits.
I tried the second example in MSVC and it didn't complain.
It does if you set the warning level to /W4; in that case it'll warn you about a non-standard extension being used. AFAIK, the semantics are the same as the previous case.
My scenario demands the default argument to constructor in this manner and I will need to modify the argument in the constructor (so I cannot make it const). And I also need to use foo after the constructor has exited.
It depends on whether you want to save it as member of Bar or not. If it's the former, use an rvalue reference and move the argument
Bar::Bar(Foo&& foo = Foo()) : f_(std::move(foo)) {} // f_ is a member of type Foo
Otherwise, just leave out the default argument. You can also create both overloads to cover different situations.
foo and its temporary are gone after the constructor completes.
It's a MS extension that doesn't follow the language standard.
Don't use temporary default values in this case. If you need to be able to access it after the constructor completes, you need to create the object yourself prior to calling the constructor, and pass that in by reference.
My scenario demands the default argument to constructor in this manner
and I will need to modify the argument in the constructor (so I cannot
make it const). And I also need to use foo after the constructor has
exited. What is the best design to cater to this scenario?
You could make an optional<Foo> inside Bar, as in:
struct Bar
{
Bar() : optionalFoo(boost::in_place()), foo(*optionalFoo) {}
Bar(Foo& f) : foo(f) {}
Bar(Bar const&) = delete; // Compiler generated one is incorrect
private:
boost::optional<Foo> optionalFoo;
Foo& foo;
};
But classes that optionally own their data get tricky, especially when it comes to copying/moving.
In this case (as in most cases), the lifetime of a temporary bound directly to a reference is extended to the lifetime of the reference. So the temporary will be valid as long as foo is, i.e. for the duration of the constructor. It will end when the full-expression containing the constructor call ends.
MSVC has an extension which allows temporaries to bind to non-const references. It's not standard and other compilers don't support it. Don't use this unless you are (and always will be) coding for MSVC only.
That depends on what you actually want to achieve - there's not enough information in your question to answer that. If you need it to persist even after the constructor exits, you need to provide an actual object with appropriate lifetime. You could provide a per-thread static member, for example:
class Bar
{
static thread_local Foo ctor_default_foo;
public:
Bar(Foo &foo = ctor_default_foo) {}
};
Note that this of course means that all objects created by one thread using the default argument would share the same Foo object. If you need a new one for each Bar object, you'll have to change your design. But to tell you how, we'd need to know more about the actual use case.

is it possible to restrict class instances to be used only as temporaries?

is it possible to restrict class instances to be used only as rvalues (e.g. temporaries)?
for example, I have class Wrapper whose constructor takes A const& and saves this reference in its member. It's a dangerous because lifetime of Wrapper instance cannot be longer than lifetime of A instance, but it's fine if Wrapper is temporary.
I think that even wanting to do this is a sign of a really bad design.
However, you could make all constructors private and make a friend function that returns an rvalue. That should do the trick.
I don't think it would be safe:
const A &a = YourClass( tmp );
YourClass in this case is the class you're looking for which only allow temporary instances, tmp is the temporary value you pass to the constructor.
It's possible (ie: safe, defined behavior) to have a constant reference to a temporary (ie: a), but the temporary itself (such instance of YourClass) has got a reference to tmp which is no longer valid after that expression is evaluated.
Not exactly the answer you are looking for, but have you thought about weak pointers? (for example, boost::weak_ptr). In this case, the original A would be held in a shared_ptr and the Wrapper constructor accepts a weak_ptr. The neat thing with this approach is that, before each usage of the weak_ptr, you can attempt to lock() which will give you a shared_ptr - if that fails, you know that A is gone and Wrapper cannot function... But it's handled cleanly...
This might do the job unless your class has public data members.
Basically, the idea is not to restrict the construction of the wrapper but to make sure that instances can be used (just like you said) only as long as they are temporary values. One can achieve this by overloading all methods and deleting (or making them private) those that refer to const&.
Here's a simple example:
class Wrapper
{
public:
Wrapper() = default;
Wrapper(const std::string& name) : name(name) {}
void process() && { std::cout << "Greetings from " << name << std::endl; }
// Only temporary instances of this class are allowed!
void process() const & = delete;
private:
std::string name;
};
And some use cases:
Wrapper("John").process(); // intended use case
Wrapper j; // create whatever you want
j.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
std::move(j).process(); // this is still possible
const Wrapper& t = Wrapper(); // bind the temporary to a const reference - not a problem because ...
t.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
The obvious disadvantages are:
You have to overload every public member function.
The error message is delayed and not very informative.
A similar thing has been done in the standard. The make routines for std::reference_wrapper do not accept temporaries.
Note that they considered another subtlety: the overload uses const T&& instead of T&&. This can be important in our case as well. For example, if your wrapper is deliberately designed to be noncopyable and you use make routines such as
const Wrapper make_wrapper();
instead of
Wrapper make_wrapper();
In this case, you might want to replace
void process() &&;
by
void process() const &&;
I'd not bother enforcing this at compile time, as there are always going to be corner cases where this would be overly restrictive, limiting the usefulness of the class, but rather wrap tools like valgrind or Purify so I can spot places where invalidated references are used.
I believe in C++17 and later you can get approximately what you want by doing the following:
Delete the move constructor for your type (and don't define a copy constructor).
Always accept your type by value in APIs.
So, for example:
#include <type_traits>
#include <utility>
// A non-moveable, non-copyable type.
struct CantMove {
CantMove(CantMove&&) = delete;
CantMove(int) {} // Some other constructor
};
static_assert(!std::is_move_constructible_v<CantMove>);
static_assert(!std::is_copy_constructible_v<CantMove>);
// A function that accepts it by value.
bool AcceptByValue(CantMove input) { return true; }
// It's possible to call the value-accepting API when the input is a prvalue
// (which in previous versions of C++ would have been a temporary).
bool unused = AcceptByValue(CantMove(0));
// But it's not possible to call with a named value, even when casted to an
// rvalue reference. This doesn't compile.
CantMove cant_move(0);
bool unused_2 = AcceptByValue(std::move(cant_move));
It's possible to provide the value-accepting function with what we previously called a temporary because guaranteed copy elision says that there isn't even a temporary involved anymore—the only CantMove object created is the function parameter itself, so there is no move- or copy-construction involved. In contrast it's not possible to call with std::move(cant_move) because that would involve move-constructing the function parameter, and the type is not move-constructible.
Of course it's still possible to initialize a CantMove directly:
CantMove foo{0};
But if you own all of the APIs that accept a CantMove and make them all accept by value, then you can't actually do anything with foo afterward. This means it would be hard for a user to do this by mistake and not realize the problem.
Yes, you could.
You would make the constructor and regular copy-constructor/assign private but make the r-value move semantics (C++0x) public.
You would have a static or friend constructor to create the temporary.
In 2003 C++ you would also be able to use this to bind to a const reference.
Of course you'd have the issue that your const reference would probably become invalidated after the statement.

C++ is there a difference between assignment inside a pass by value and pass by reference function?

Is there a difference between foo and bar:
class A
{
Object __o;
void foo(Object& o)
{
__o = o;
}
void bar(Object o)
{
__o = o;
}
}
As I understand it, foo performs no copy operation on object o when it is called, and one copy operation for assignment. Bar performs one copy operation on object o when it is called and another one for assignment. So I can more or less say that foo uses 2 times less memory than bar (if o is big enough). Is that correct ?
Is it possible that the compiler optimises the bar function to perform only one copy operation on o ? i.e. makes __o pointing on the local copy of argument o instead of creating a new copy?
It depends. For example, if the compiler decides to inline the function, obviously there will be no copy since there is no function call.
If you want to be sure, pass by const-reference:
void bar(const Object& o)
This makes no copies. Note your non-const version requires an lvalue, because the reference is mutable. foo(Object()) wouldn't work, but temporaries (rvalues) can be bound to a const-reference.
Double-underscores in identifiers are reserved for the compiler, by the way.
Since assignment typically takes const Something& as a parameter, it would be canonical to write:
void foo(const Object& o)
{
__o = o;
}
But this does not answer your question about the optimization. I'm not sure that, in general, such optimization can / will be made by the compiler.
I think its fair to say that foo() performs one less copy than bar(). Its not very meaningful to say how much more or less memory is consumed, because for simple objects they are stored on the stack and cleaned up after return from bar().
As has been said, don't use underscores at the start of identifiers.
I think compilers can do the optimization in case of temporary objects. This technique is called copy elision.
Please refer to the answers to question i had posted what-is-copy-elision-and-how-it-optimizes-copy-and-swap-idiom. This ans is really helpful What is copy elision and how does it optimize the copy-and-swap idiom?
Though i am not an expert in this, from what i understand compliers can optimize copying of temporary object in some scenarios.
For example if your code is called like this
bar(getObject())
where getObject has a signature
Object getObject()
This call will result in creation of a temporary of type Object. If the compiler does not do any optimization that temporay has to be copied into the argument to bar.
However if compiler supports copy elision this copying wont be performed and the temporary will be passed as an argument to bar function. So the copy is avoided and its performance is same as foo which accepts a reference. But as i said it happens only in case of temporary object

Is it more efficient to return a const reference

E.g.
What's best out of these:
std::string f() {}
or
const std::string& f() {}
A function should never return a reference to a local object/variable since such objects go out of the scope and get destroyed when the function returns.
Differently, the function can return a const or non const reference to an object whose scope is not limited by the function context. Typical example is a custom operator<<:
std::ostream & operator<<(std::ostream &out, const object &obj)
{
out << obj.data();
return out;
}
Unfortunately, returning-by-value has its performance drawback. As Chris mentioned, returning an object by value involves the copy of a temporary object and its subsequent destruction. The copy takes place by means of either copy constructor or operator=. To avoid these inefficiencies, smart compilers may apply the RVO or the NRVO optimizations, but there are cases in which they can't -- multiple returns.
The upcoming C++0x standard, partially available in gnu gcc-4.3, introduces the rvalue reference [&&] that can be used to distinguish a lvalue from a rvalue reference. By means of that, it's possible to implement the move constructor, useful to return an object partially avoiding the cost of copy constructor and the destructor of the temporary.
The move constructor is basically what Andrei envisioned some years ago in the article http://www.ddj.com/database/184403855 suggested by Chris.
A move constructor has the following signature:
// move constructor
object(object && obj)
{}
and it's supposed to take the ownership of the internals of the passed object leaving the latter in a default state. By doing that, copies of internals are avoided and the destruction of the temporary made easy. A typical function factory will then have the following form:
object factory()
{
object obj;
return std::move(obj);
}
The std::move() returns a rvalue reference from an object. Last but not least, move constructors allow the return-by-rvalue-reference of non-copyable objects.
I would like to add to Nicola's excellent answer. Yes, you must never return a dangling reference (e.g., reference to a local variable), however, there are three useful ways to improve performance in those cases:
Return-value optimisation (RVO): You return by value, but eliminate copying by having only one return statement, which creates the return value on the spot. Here's an example of RVO being used: How can I tokenize a C++ string?
Named return-value optimisation (NRVO): You return by value, and declare the return value variable first, at the top of the function. All return statements return that variable. With compilers that support NRVO, that variable is allocated in the return-value slot, and does not get copied upon return. e.g.,
string
foobar()
{
string result;
// fill in "result"
return result;
}
Use a shared_ptr or the like as the return type; this necessitates creating your object on the heap, rather than the stack. This prevents dangling-reference problems while still not requiring the whole object to be copied, just the smart pointer.
By the way, I can't take credit for the information about RVO and NRVO; they come straight out of Scott Meyers's More Effective C++. Since I don't have the book with me at the moment, any errors in my description are my doing, not Scott's. :-)
If you return a reference to a variable that is local to the function then you're going to end up with issues (depending on the compiler and its settings).
If you return a reference to an instance that's still in scope when the function returns then it will be faster, as no copy of the string is being created.
So the latter is more efficient (technically) but may not function as expected depending on what you return a reference to.