Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Comments on Do you need to use std::move to store a parameter passed by value?

Parent

Do you need to use std::move to store a parameter passed by value?

+3
−0

If you have a class which needs to store a construction parameter internally, and you want to take advantage of move semantics, I understand that the parameter should be passed by value:

class Foo {
    std::string _string;
public:
    Foo(std::string s): _string(s) {}
};
...
Foo foo(std::string("Temporary value")); // rvalue is moved in

However I'm a little unclear on the code required inside the constructor. Do you need to use std::move to preserve the rvalue reference, e.g.

    Foo(std::string s): _string(std::move(s)) {}

or does the compiler treat the parameter s as a moveable value by default (since it's going to be destroyed at the end of the function body), rendering the std::move unnecessary:

    Foo(std::string s): _string(s) {}
History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

Post
+3
−0

Update: Distinguished between the general case and cases (as with std::string) where it is known that there are no side effects.

In the general case, the substitution of the call to a copy constructor by a call to a move constructor could lead to a different behavior: The two constructors might have different side effects. Thus, such an optimization might result in a different behavior of the compiled code.

This is normally not accepted for optimizations: The normal assumption is, that an optimization may have an impact on performance or memory consumption, but does not change the behavior otherwise. (Side note: A special situation is, when the code does not strictly comply with the language rules anyway and therefore formally has undefined behavior, but that's a special case...)

For C++, however, there are some exceptions to this usual approach to optimization: In clearly specified circumstances the compiler is allowed (or even mandated) to eliminate copy/move operations even if that results in different behavior, see https://en.cppreference.com/w/cpp/language/copy_elision.

Still, in all other situations, optimizations shall not alter the behavior. This means that the compiler is not generally allowed to implicitly substitute the copy by the move operation.

In your example, however, you are dealing with std::string. As std::string is defined by the standard, the compiler knows, that there are no side effects in the constructors. In such cases, where it is known there are no side effects, the compiler can perform all kinds of optimizations, including (but not limited to) replacing copy by move operations.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

1 comment thread

So in this example, it doesn't matter that the string argument to `Foo()` is a temporary — the tempor... (2 comments)
So in this example, it doesn't matter that the string argument to `Foo()` is a temporary — the tempor...
deleted user wrote over 2 years ago

So in this example, it doesn't matter that the string argument to Foo() is a temporary — the temporary string has to be copied because the Foo class does not provide a std::string&& constructor?

Dirk Herrmann‭ wrote over 2 years ago

If the compiler knows that there are no side effects, it can perform all kinds of optimizations. And, for the std::string constructor the compiler knows there are no side effects, as it is defined by the standard. The copy elision rules only have relevance where there are known side effects or where compiler does not know about possible side effects. Therefore, the temporary string may be moved by the compiler because of this knowledge - but possibly further optimizations are possible. I recommend to try some examples using the godbolt compiler (with and without -O3) and you will see, what happens.