Avoiding copy of objects with the return statement
This program can take advantage of named return value optimization (NRVO). See here: http://en.wikipedia.org/wiki/Copy_elision
In C++11 there are move constructors and assignment which are also cheap. You can read a tutorial here: http://thbecker.net/articles/rvalue_references/section_01.html
Does return statement copy values
Yes, in that case there will be a copy made. If you change the function declaration like this:
subline_t &subline(int x1, int x2, int id) {
then no copy will be made. However, in your specific case it would not be valid to return a reference to an object allocated on the stack. The problem is that the object would be destructed and invalidated before the caller had a chance to use it.
This is related to the common Return Value Optimization for C++ that can avoid doing an actual copy operation in the case you have described. The end result is (or should be) the same as if a copy were done, but you should be aware of the optimization. The presence of this optimization can, in some cases, change the observable behaviour of the program.
Prevent object copy on return
You need to return by value instead of reference. Using
Point getPoint()
{
return { 100, 120 };
}
Allows C++17's guaranteed copy elision to kick in which causes Point p = getPoint();
to act as if it was Point p{ 100, 120 };
Side note: Never, Never, Never, return a function local object by reference. That object will be destroyed at the end of the function leaving you with a dangling reference and using that is undefined behavior.
How to avoid using a return statement in a for-in loop?
As @quamrana, I think that the loop is implemented well, except that you store posts only for the last loop run. Here is the correction:
def followingPosts(request, user_username):
try:
user_profile = get_object_or_404(User, username=user_username)
following_users = user_profile.get_following()
posts = list()
for person in following_users:
posts += Post.objects.filter(creator=person)
except Profile.DoesNotExist:
return JsonResponse({"error": "No user found."}, status=404)
if request.method == "GET":
return JsonResponse([post.serialize() for post in posts], safe=False)
else:
return JsonResponse({
"error": "GET request required."
}, status=400)
Also, it is a good habit to keep a single line in the try-clause. Therefore, what about
def followingPosts(request, user_username):
try:
user_profile = get_object_or_404(User, username=user_username)
except Profile.DoesNotExist:
return JsonResponse({"error": "No user found."}, status=404)
if request.method == "GET":
following_users = user_profile.get_following()
posts = list()
for person in following_users:
posts += Post.objects.filter(creator=person)
return JsonResponse([post.serialize() for post in posts], safe=False)
else:
return JsonResponse({
"error": "GET request required."
}, status=400)
C++ Return temporary values and objects that cannot be copied
Go ahead and let the default copy constructors be public. And document that a view
or mutable_view
is "invalidated" when its tensor
is changed or destroyed.
This parallels how the Standard Library deals with iterators, pointers, and references that have a lifetime which depends on another object.
Is it possible to avoid the copy constructor when passing newly created object to a function?
Pass by value implies copying. This copying can be elided but semantically pass by value is still copying. You can pass by reference as well to avoid this copy. Note that these are the only situations in which copy elision are permitted:
- in a return statement
- in a throw-expression
- with a temporary that hasn't been bound to a reference
- and another to do with exceptions
That's why in:
bar(f);
bar(Foo());
only the second involves copy elision. Pre-C++11, just use a reference or use Boost.
Initialization in return statements of functions that return by-value
You have to be careful with cppreference.com when diving into such nitty-gritty, as it's not an authoritative source.
So which object exactly is copy-initialized as described at cppreference.com for return statements?
In this case, none. That's what copy elision is: The copy that would normally happen is skipped. The cppreference (4) clause could be written as "when returning from a function that returns by value, and the copy is not elided", but that's kind of redundant. The standard: [stmt.return] is a lot clearer on the subject.
To convert from A&& to A A's move constructor is used, which is also why NRVO is disabled here. Are those the rules that apply in this case, and did I understand them correctly?
That's not quite right. NRVO only applies to names of non-volatile objects. However, in return std::move(local);
, it's not local
that is being returned, it's the A&&
that is the result of the call to std::move()
. This has no name, thus mandatory NRVO does not apply.
I think this should be an Lvalue to rvalue conversion:
The A&&
returned by std::move()
is decidedly not an Lvalue. It's an xvalue, and thus an rvalue already. There is no Lvalue to rvalue conversion happening here.
but A a2(no_nrvo()); is a direct initialization. So this also touches on the first case.
Not really. Whether a function has to perform copy-initialization of its result as part of a return
statement is not impacted in any way by how that function is invoked. Similarly, how a function's return argument is used at the callsite is not impacted by the function's definition.
In both cases, an
is direct-initialized by the result of the function. In practice, this means that the compiler will use the same memory location for the an
object as for the return value of the function.
In A a1(nrvo());
, thanks to NRVO, the memory location assigned to local
is the same as the function's result value, which happens to be a1
already. Effectively, local
and a1
were the same object all along.
In A a2(no_nrvo())
, local
has its own storage, and the result of the function, aka a2
is move-constructed from it. Effectively, local
is moved into a2
.
Will std::move() upon object construction in return statement help or prevent RVO?
// version 1
MyObject Widget::GetSomething() {
return MyObject();
}
In C++03 this requires MyObject
by copyable. At runtime, no copy will be made using any "real" compiler with reasonable settings as the standard permits elision here.
In C++11 or 14 it requires the object be movable or copyable. Elision remains; no move or copy is done.
In C++17 there is no move or copy here to elide.
In every case, in practice, MyObject
is directly constructed in the return value.
// version 2
MyObject Widget::GetSomething() {
return std::move(MyObject());
}
This is invalid in C++03.
In C++11 and beyond, MyObject
is moved into the return value. The move must occur at runtime (barring as-if elimination).
// version 3
MyObject Widget::GetSomething() {
auto obj = MyObject();
return obj;
}
Identical to version 1, except C++17 behaves like C++11/14. In addition, the elision here is more fragile; seemingly innocuous changes could force the compiler to actually move obj
.
Theoretically 2 moves are elided here in C++11/14/17 (and 2 copies in C++03). The first elision is safe, the second fragile.
// version 4
MyObject Widget::GetSomething() {
auto obj = MyObject();
return std::move(obj);
}
In practice this behaves just like version 2. An extra move (copy in C++03) occurs in constructing obj
but it is elided, so nothing happens at runtime.
Elision permits the elimination of side effects of the copy/move; the objects lifetimes are merged into one object, and the move/copy is eliminated. The constructor still has to exist, it is just never called.
Answer
Both 1 and 3 will compile to identical runtime code. 3 is slightly more fragile.
Both 2 and 4 compile to identical runtime code. It should never be faster than 1/3, but if the move can be eliminated by the compiler proving not doing it is the same as-if doing it, it could compile to the same runtime code as 1/3. This is far from guaranteed, and extremely fragile.
So 1>=3>=2>=4
is the order of faster to slower in practice, where "more fragile" code that is otherwise the same speed is <=
.
As an example of a case that could make 3 slower than 1, if you had an if statement:
// version 3 - modified
MyObject Widget::GetSomething() {
auto obj = MyObject();
if (err()) return MyObject("err");
return obj;
}
suddenly many compilers will be forced to move obj
into the return value instead of eliding obj
and the return value together.
Why is the copy constructor called when we return an object from a method by value
The copy constructor is called because you call by value not by reference. Therefore a new object must be instantiated from your current object since all members of the object should have the same value in the returned instance. Because otherwise you would be returning the object it self, which would be returning by reference. In this case modifying the reference object would change the original as well. This is generally not a behavior one wants when returning by value.
Related Topics
Are Multiple Mutations of the Same Variable Within Initializer Lists Undefined Behavior Pre C++11
Intrinsics for Cpuid Like Informations
What Are the Issues with a Vector-Of-Vectors
Why Is This Cin Reading Jammed
Should I Store Entire Objects, or Pointers to Objects in Containers
How to Have Swift, Objective-C, C and C++ Files in the Same Xcode Project
Efficient Thread-Safe Singleton in C++
What Does "#Pragma Comment" Mean
Understanding Recursion to Generate Permutations
Cast Pointer to Member Function to Normal Pointer
Why Is Initializing an Integer in C++ to 010 Different from Initializing It to 10
How to Reset Std::Cin When Using It
Compare Two Float Variables in C++
*.H or *.Hpp for Your Class Definitions