Why You Should Only Rarely Use std::move (2024)

std::move can allow the efficient transfer of resources from object to to object. Andreas Fertig reminds us that using std::move inappropriately can make code less efficient.

In this article, I try to tackle a topic that comes up frequently in my classes: move semantics, and when to use std::move. I will explain to you why you should suggest std::move yourself (in most cases). However, move semantics is way bigger than what this article covers, so don’t expect a full guide to the topic.

Looking More Closely

For a deeper dive, see ‘Nothing is better than copy or move’ [Orr18].

C++11 introduced ‘move semantics’ to facilitate transferring the contents of one object to another more efficiently than creating a copy and then erasing the original. This is particularly focused on optimising the performance of temporary objects, such as when passing them into or out of a function call.

However, in all the discussions about copying and moving, it is easy to forget that not creating an object in the first place may be even more efficient. This can be something done by design choice, or an optimisation applied during compilation. For example, introduction of a temporary object by copying can be removed; this is is called ‘copy elision’ in C++ and has been permitted in the language for many years.

C++17 adds some additional specification around the creation of temporary variables with the phrase ‘temporary materialization’.

Rog’s presentation looks at some ‘worked examples’ of how this behaves in practice, and some things to be aware of.

The example in Listing 1 is the code I used to make my point: don’t use std::move on temporaries! Plus, in general, trust the compiler and only use std::move rarely. For this article, let’s focus on the example code.

class S {public: S() { printf("default constructor\n"); } ~S() { printf("deconstructor\n"); } // Copy constructor  S(const S&) { printf("copy constructor\n"); } // Move constructor  S(S&&) { printf("move constructor\n"); }};void Use(){ S obj{ S{} // Creating obj with a temporary of S  };}
Listing 1

Here we see a, well, perfectly movable class. I left the assignment operations out. They are not relevant. Aside from the constructor and destructor, we see in the copy constructor and in the move constructor. All special members print a message to identify them when they are called.

Further down in Use, we see , a temporary object of S used to initialize obj, also of type S. This is the typical situation where move semantics excels over a copy (assuming the class in question has movable members). The output I expect, and I wanted to show my participants, is:

 default constructor move constructor deconstructor deconstructor

However, the resulting output was:

 default constructor deconstructor

Performance-wise, the output doesn’t look bad, but it doesn’t show a move construction. The question is, what is going on here?

This is the time to apply std::move, right?

At this point, somebody’s suggestion was to add std::move.

 void Use() { S obj{ // Moving the temporary into obj std::move(S{}) }; }

This change indeed leads to the desired output:

 default constructor move constructor deconstructor deconstructor

It looks like we just found proof that std::move is required all the time. The opposite is the case! std::move makes things worse here. To understand why, let’s first talk about the C++ standard I used to compile this code.

Wait a moment!

In C++14, the output is what I showed you for both Clang and GCC. Even if we compile with -O0 that doesn’t change a thing. We need std::move to see that the move constructor is called. The key here is that the compiler can optimize the temporary away, resulting in only a single default construction. We shouldn’t see a move here because the compiler is already able to optimize it away. The best move operation will not help us here. Nothing is better than eliding a certain step. Eliding is the keyword here. To see what is going on, we need to use the -fno-elide-constructors flag, which Clang and GCC support.

Now the output changes. Running the initial code, without std::move, in C++14 mode shows the expected output:

 default constructor move constructor deconstructor deconstructor

If we now switch to C++17 as the standard, the output is once again:

 default constructor deconstructor

Due to the mandatory copy elision in C++17, the compiler must elide this nonsense construction even with -fno-elide-constructors. However, if we apply std::move to the temporary copy, elision doesn’t apply anymore, and we’re back to seeing a move construction.

You can verify this on Compiler Explorer: godbolt.org/z/G1ebj9Yjj

The take away

That means, hands-off! Don’t move temporary objects! The compiler does better without us.

References

[Orr18] Roger Orr, ‘Nothing is better than copy or move’ presentation given at ACCU 2018, available at: https://youtu.be/-dc5vqt2tgA

Andreas Fertig is a trainer and lecturer on C++11 to C++20, who presents at international conferences. Involved in the C++ standardization committee, he has published articles (for example, in iX) and several textbooks, most recently Programming with C++20. His tool – C++ Insights (https://cppinsights.io) – enables people to look behind the scenes of C++, and better understand constructs.

This article was published on Andreas Fertig’s blog in February 2022 (https://andreasfertig.blog/2022/02/why-you-should-use-stdmove-only-rarely/).

Why You Should Only Rarely Use std::move (2024)
Top Articles
The US is changing the face of the $10 bill
Best Homemade Carpet Cleaner Solution - HappyMoneySaver
English Bulldog Puppies For Sale Under 1000 In Florida
Katie Pavlich Bikini Photos
Gamevault Agent
Pieology Nutrition Calculator Mobile
Hocus Pocus Showtimes Near Harkins Theatres Yuma Palms 14
Hendersonville (Tennessee) – Travel guide at Wikivoyage
Compare the Samsung Galaxy S24 - 256GB - Cobalt Violet vs Apple iPhone 16 Pro - 128GB - Desert Titanium | AT&T
Vardis Olive Garden (Georgioupolis, Kreta) ✈️ inkl. Flug buchen
Craigslist Dog Kennels For Sale
Things To Do In Atlanta Tomorrow Night
Non Sequitur
Crossword Nexus Solver
How To Cut Eelgrass Grounded
Pac Man Deviantart
Alexander Funeral Home Gallatin Obituaries
Energy Healing Conference Utah
Geometry Review Quiz 5 Answer Key
Hobby Stores Near Me Now
Icivics The Electoral Process Answer Key
Allybearloves
Bible Gateway passage: Revelation 3 - New Living Translation
Yisd Home Access Center
Pearson Correlation Coefficient
Home
Shadbase Get Out Of Jail
Gina Wilson Angle Addition Postulate
Celina Powell Lil Meech Video: A Controversial Encounter Shakes Social Media - Video Reddit Trend
Walmart Pharmacy Near Me Open
Marquette Gas Prices
A Christmas Horse - Alison Senxation
Ou Football Brainiacs
Access a Shared Resource | Computing for Arts + Sciences
Vera Bradley Factory Outlet Sunbury Products
Pixel Combat Unblocked
Movies - EPIC Theatres
Cvs Sport Physicals
Mercedes W204 Belt Diagram
Mia Malkova Bio, Net Worth, Age & More - Magzica
'Conan Exiles' 3.0 Guide: How To Unlock Spells And Sorcery
Teenbeautyfitness
Where Can I Cash A Huntington National Bank Check
Topos De Bolos Engraçados
Sand Castle Parents Guide
Gregory (Five Nights at Freddy's)
Grand Valley State University Library Hours
Hello – Cornerstone Chapel
Stoughton Commuter Rail Schedule
Nfsd Web Portal
Selly Medaline
Latest Posts
Article information

Author: Pres. Carey Rath

Last Updated:

Views: 6328

Rating: 4 / 5 (41 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Pres. Carey Rath

Birthday: 1997-03-06

Address: 14955 Ledner Trail, East Rodrickfort, NE 85127-8369

Phone: +18682428114917

Job: National Technology Representative

Hobby: Sand art, Drama, Web surfing, Cycling, Brazilian jiu-jitsu, Leather crafting, Creative writing

Introduction: My name is Pres. Carey Rath, I am a faithful, funny, vast, joyous, lively, brave, glamorous person who loves writing and wants to share my knowledge and understanding with you.