100% found this document useful (1 vote)
45 views84 pages

C Move Semantics The Complete Guide 1st Edition Nicolai M Josuttis Instant Download

C++ Move Semantics - The Complete Guide by Nicolai M. Josuttis provides a comprehensive exploration of move semantics in C++. The book covers the motivation, implementation, and core features of move semantics, including practical examples and guidelines for using it effectively in C++ programming. It is published on Leanpub and is available for purchase online.

Uploaded by

kraahwunmi23
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
45 views84 pages

C Move Semantics The Complete Guide 1st Edition Nicolai M Josuttis Instant Download

C++ Move Semantics - The Complete Guide by Nicolai M. Josuttis provides a comprehensive exploration of move semantics in C++. The book covers the motivation, implementation, and core features of move semantics, including practical examples and guidelines for using it effectively in C++ programming. It is published on Leanpub and is available for purchase online.

Uploaded by

kraahwunmi23
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 84

C Move Semantics The Complete Guide 1st Edition

Nicolai M Josuttis download

https://ebookbell.com/product/c-move-semantics-the-complete-
guide-1st-edition-nicolai-m-josuttis-46824864

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

C Move Semantics The Complete Guide Ebook Nicolai M Josuttis

https://ebookbell.com/product/c-move-semantics-the-complete-guide-
ebook-nicolai-m-josuttis-23272572

C Move Semantics The Complete Guide Nicolai M Josuttis

https://ebookbell.com/product/c-move-semantics-the-complete-guide-
nicolai-m-josuttis-46703930

Every Move You Make Cl Taylor

https://ebookbell.com/product/every-move-you-make-cl-taylor-56470666

Every Move You Make Cl Taylor

https://ebookbell.com/product/every-move-you-make-cl-taylor-57477872
China On The Move Migration The State And The Household 1st Edition C
Cindy Fan

https://ebookbell.com/product/china-on-the-move-migration-the-state-
and-the-household-1st-edition-c-cindy-fan-1634230

Christians On The Move The Book Of Acts Henrietta C Mears

https://ebookbell.com/product/christians-on-the-move-the-book-of-acts-
henrietta-c-mears-38261912

Medical Sociology On The Move New Directions In Theory 1st Edition


William C Cockerham Ed

https://ebookbell.com/product/medical-sociology-on-the-move-new-
directions-in-theory-1st-edition-william-c-cockerham-ed-4412034

Overcoming Imposter Anxiety Move Beyond Fear Of Failure And Selfdoubt


To Embrace Your Worthy Capable Self Ijeoma C Nwaogu

https://ebookbell.com/product/overcoming-imposter-anxiety-move-beyond-
fear-of-failure-and-selfdoubt-to-embrace-your-worthy-capable-self-
ijeoma-c-nwaogu-53681510

Overcoming Imposter Anxiety Move Beyond Fear Of Failure And Selfdoubt


To Embrace Your Worthy Capable Self 1st Edition Ijeoma C Nwaogu

https://ebookbell.com/product/overcoming-imposter-anxiety-move-beyond-
fear-of-failure-and-selfdoubt-to-embrace-your-worthy-capable-self-1st-
edition-ijeoma-c-nwaogu-56037458
Josuttis: C++ Move Semantics 2022/04/19 13:28 page i

Nicolai M. Josuttis

C++ Move Semantics - The Complete Guide

First Edition
Josuttis: C++ Move Semantics 2022/04/19 13:28 page ii

C++ Move Semantics - The Complete Guide


First Edition

Nicolai M. Josuttis

This version was published on 2022-04-19.

© 2022 by Nicolai Josuttis. All rights reserved.


This publication is protected by copyright, and permission must be obtained from the author prior
to any prohibited reproduction, storage in a retrieval system, or transmission in any form or by any
means, electronic, mechanical, photocopying, recording, or likewise.

This book was typeset by Nicolai M. Josuttis using the LATEX document processing system.

This book is for sale at http://leanpub.com/cppmove.


This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing
process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and
many iterations to get reader feedback, pivot until you have the right book, and build traction once
you do.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page iii

Contents
Preface xi
An Experiment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
Versions of This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xii
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii

About This Book xv


What You Should Know Before Reading This Book . . . . . . . . . . . . . . . . . . . . . . . . . . xv
Overall Structure of the Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv
How to Read This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi
The Way I Implement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi
The C++ Standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii
Example Code and Additional Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xviii
Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xviii

Part I: Basic Features of Move Semantics 1

1 The Power of Move Semantics 3


1.1 Motivation for Move Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1 Example with C++03 (Before Move Semantics) . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 Example Since C++11 (Using Move Semantics) . . . . . . . . . . . . . . . . . . . . . 11
1.2 Implementing Move Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.2.1 Using the Copy Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.2.2 Using the Move Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.3 Copying as a Fallback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.4 Move Semantics for const Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.4.1 const Return Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

iii
Josuttis: C++ Move Semantics 2022/04/19 13:28 page iv

iv Contents

1.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2 Core Features of Move Semantics 25


2.1 Rvalue References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.1.1 Rvalue References in Detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.1.2 Rvalue References as Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.2 std::move() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.2.1 Header File for std::move() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.2.2 Implementation of std::move() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.3 Moved-From Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.3.1 Valid but Unspecified State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.3.2 Reusing Moved-From Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.3.3 Move Assignments of Objects to Themselves . . . . . . . . . . . . . . . . . . . . . . . 30
2.4 Overloading by Different References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.4.1 const Rvalue References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.5 Passing by Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3 Move Semantics in Classes 35


3.1 Move Semantics in Ordinary Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.1.1 When is Move Semantics Automatically Enabled in Classes? . . . . . . . . . . . . . 38
3.1.2 When Generated Move Operations Are Broken . . . . . . . . . . . . . . . . . . . . . 39
3.2 Implementing Special Copy/Move Member Functions . . . . . . . . . . . . . . . . . . . . . . 40
3.2.1 Copy Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.2.2 Move Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.2.3 Copy Assignment Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.2.4 Move Assignment Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.2.5 Using the Special Copy/Move Member Functions . . . . . . . . . . . . . . . . . . . . 46
3.3 Rules for Special Member Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.3.1 Special Member Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.3.2 By Default, We Have Copying and Moving . . . . . . . . . . . . . . . . . . . . . . . . 50
3.3.3 Declared Copying Disables Moving (Fallback Enabled) . . . . . . . . . . . . . . . . 50
3.3.4 Declared Moving Disables Copying . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.3.5 Deleting Moving Makes No Sense . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.3.6 Disabling Move Semantics with Enabled Copy Semantics . . . . . . . . . . . . . . . 53
Josuttis: C++ Move Semantics 2022/04/19 13:28 page v

Contents v

3.3.7 Moving for Members with Disabled Move Semantics . . . . . . . . . . . . . . . . . . 54


3.3.8 Exact Rules for Generated Special Member Functions . . . . . . . . . . . . . . . . . 54
3.4 The Rule of Five or Three . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

4 How to Benefit From Move Semantics 59


4.1 Avoid Objects with Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.1.1 When You Cannot Avoid Using Names . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.2 Avoid Unnecessary std::move() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.3 Initialize Members with Move Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.3.1 Initialize Members the Classical Way . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.3.2 Initialize Members via Moved Parameters Passed by Value . . . . . . . . . . . . . . 63
4.3.3 Initialize Members via Rvalue References . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.3.4 Compare the Different Approaches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.3.5 Summary for Member Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.3.6 Should We Now Always Pass by Value and Move? . . . . . . . . . . . . . . . . . . . 73
4.4 Move Semantics in Class Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.4.1 Implementing a Polymorphic Base Class . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.4.2 Implementing a Polymorphic Derived Class . . . . . . . . . . . . . . . . . . . . . . . 77
4.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

5 Overloading on Reference Qualifiers 79


5.1 Return Type of Getters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
5.1.1 Return by Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
5.1.2 Return by Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.1.3 Using Move Semantics to Solve the Dilemma . . . . . . . . . . . . . . . . . . . . . . 81
5.2 Overloading on Qualifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.3 When to Use Reference Qualifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
5.3.1 Reference Qualifiers for Assignment Operators . . . . . . . . . . . . . . . . . . . . . 84
5.3.2 Reference Qualifiers for Other Member Functions . . . . . . . . . . . . . . . . . . . . 86
5.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

6 Moved-From States 89
6.1 Required and Guaranteed States of Moved-From Objects . . . . . . . . . . . . . . . . . . . . . 89
6.1.1 Required States of Moved-From Objects . . . . . . . . . . . . . . . . . . . . . . . . . 90
Josuttis: C++ Move Semantics 2022/04/19 13:28 page vi

vi Contents

6.1.2 Guaranteed States of Moved-From Objects . . . . . . . . . . . . . . . . . . . . . . . . 91


6.1.3 Broken Invariants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
6.2 Destructible and Assignable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.2.1 Assignable and Destructible Moved-From Objects . . . . . . . . . . . . . . . . . . . 93
6.2.2 Non-Destructible Moved-From Objects . . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.3 Dealing with Broken Invariants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
6.3.1 Breaking Invariants Due to a Moved Value Member . . . . . . . . . . . . . . . . . . . 97
6.3.2 Breaking Invariants Due to Moved Consistent Value Members . . . . . . . . . . . . 100
6.3.3 Breaking Invariants Due to Moved Pointer-Like Members . . . . . . . . . . . . . . . 102
6.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

7 Move Semantics and noexcept 107


7.1 Move Constructors with and without noexcept . . . . . . . . . . . . . . . . . . . . . . . . . . 107
7.1.1 Move Constructors without noexcept . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
7.1.2 Move Constructors with noexcept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
7.1.3 Is noexcept Worth It? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
7.2 Details of noexcept Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
7.2.1 Rules for Declaring Functions with noexcept . . . . . . . . . . . . . . . . . . . . . . 116
7.2.2 noexcept for Special Member Functions . . . . . . . . . . . . . . . . . . . . . . . . . 117
7.3 noexcept Declarations in Class Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
7.3.1 Checking for noexcept Move Constructors in Abstract Base Classes . . . . . . . . 120
7.4 When and Where to Use noexcept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
7.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

8 Value Categories 125


8.1 Value Categories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
8.1.1 History of Value Categories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
8.1.2 Value Categories Since C++11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
8.1.3 Value Categories Since C++17 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
8.2 Special Rules for Value Categories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
8.2.1 Value Category of Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
8.2.2 Value Category of Data Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
8.3 Impact of Value Categories When Binding References . . . . . . . . . . . . . . . . . . . . . . 133
8.3.1 Overload Resolution with Rvalue References . . . . . . . . . . . . . . . . . . . . . . . 133
8.3.2 Overloading by Reference and Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Josuttis: C++ Move Semantics 2022/04/19 13:28 page vii

Contents vii

8.4 When Lvalues become Rvalues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135


8.5 When Rvalues become Lvalues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
8.6 Checking Value Categories with decltype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
8.6.1 Using decltype to Check the Type of Names . . . . . . . . . . . . . . . . . . . . . . 136
8.6.2 Using decltype to Check the Value Category . . . . . . . . . . . . . . . . . . . . . . 137
8.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

Part II: Move Semantics in Generic Code 139

9 Perfect Forwarding 141


9.1 Motivation for Perfect Forwarding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
9.1.1 What we Need to Perfectly Forward Arguments . . . . . . . . . . . . . . . . . . . . . 141
9.2 Implementing Perfect Forwarding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
9.2.1 Universal (or Forwarding) References . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
9.2.2 std::forward<>() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
9.2.3 The Effect of Perfect Forwarding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3 Rvalue References versus Universal References . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.3.1 Rvalue References of Actual Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
9.3.2 Rvalue References of Function Template Parameters . . . . . . . . . . . . . . . . . . 148
9.4 Overload Resolution with Universal References . . . . . . . . . . . . . . . . . . . . . . . . . . 149
9.4.1 Fixing Overload Resolution with Universal References . . . . . . . . . . . . . . . . . 150
9.5 Perfect Forwarding in Lambdas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
9.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

10 Tricky Details of Perfect Forwarding 153


10.1 Universal References as Non-Forwarding References . . . . . . . . . . . . . . . . . . . . . . . 153
10.1.1 Universal References and const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
10.1.2 Universal References in Detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
10.1.3 Universal References of Specific Types . . . . . . . . . . . . . . . . . . . . . . . . . . 157
10.2 Universal or Ordinary Rvalue Reference? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
10.2.1 Rvalue References of Members of Generic Types . . . . . . . . . . . . . . . . . . . . 159
10.2.2 Rvalue References of Parameters in Class Templates . . . . . . . . . . . . . . . . . . 161
10.2.3 Rvalue References of Parameters in Full Specializations . . . . . . . . . . . . . . . . 162
10.3 How the Standard Specifies Perfect Forwarding . . . . . . . . . . . . . . . . . . . . . . . . . . 164
10.3.1 Explicit Specification of Types for Universal References . . . . . . . . . . . . . . . . 166
Josuttis: C++ Move Semantics 2022/04/19 13:28 page viii

viii Contents

10.3.2 Conflicting Template Parameter Deduction with Universal References . . . . . . . 167


10.3.3 Pure RValue References of Generic Types . . . . . . . . . . . . . . . . . . . . . . . . . 168
10.4 Nasty Details of Perfect Forwarding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
10.4.1 “Universal” versus “Forwarding” Reference . . . . . . . . . . . . . . . . . . . . . . . 169
10.4.2 Why && for Both Ordinary Rvalues and Universal References? . . . . . . . . . . . . 170
10.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

11 Perfect Passing with auto&& 173


11.1 Default Perfect Passing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
11.1.1 Default Perfect Passing in Detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
11.2 Universal References with auto&& . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
11.2.1 Type Deduction of auto&& . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
11.2.2 Perfectly Forwarding an auto&& Reference . . . . . . . . . . . . . . . . . . . . . . . . 177
11.3 auto&& as Non-Forwarding Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
11.3.1 Universal References and the Range-Based for Loop . . . . . . . . . . . . . . . . . 178
11.4 Perfect Forwarding in Lambdas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
11.5 Using auto&& in C++20 Function Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . 183
11.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

12 Perfect Returning with decltype(auto) 185


12.1 Perfect Returning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
12.2 decltype(auto) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
12.2.1 Return Type decltype(auto) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
12.2.2 Deferred Perfect Returning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
12.2.3 Perfect Forwarding and Returning with Lambdas . . . . . . . . . . . . . . . . . . . . 191
12.3 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

Part III: Move Semantics in the C++ Standard Library 193

13 Move-Only Types 195


13.1 Declaring and Using Move-Only Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
13.1.1 Declaring Move-Only Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
13.1.2 Using Move-Only Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
13.1.3 Passing Move-Only Objects as Arguments . . . . . . . . . . . . . . . . . . . . . . . . 197
13.1.4 Returning Move-Only Objects by Value . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Josuttis: C++ Move Semantics 2022/04/19 13:28 page ix

Contents ix

13.1.5 Moved-From States of Move-Only Objects . . . . . . . . . . . . . . . . . . . . . . . . 198


13.2 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

14 Moving Algorithms and Iterators 201


14.1 Moving Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
14.2 Removing Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
14.3 Move Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
14.3.1 Move Iterators in Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
14.3.2 Move Iterators in Constructors and Member Functions . . . . . . . . . . . . . . . . . 209
14.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210

15 Move Semantics in Types of the C++ Standard Library 211


15.1 Move Semantics for Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
15.1.1 String Assignments and Capacity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
15.2 Move Semantics for Containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
15.2.1 Basic Move Support for Containers as a Whole . . . . . . . . . . . . . . . . . . . . . 214
15.2.2 Insert and Emplace Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
15.2.3 Move Semantics for std::array<> . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
15.3 Move Semantics for Vocabulary Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
15.3.1 Move Semantics for Pairs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
15.3.2 Move Semantics for std::optional<> . . . . . . . . . . . . . . . . . . . . . . . . . 223
15.4 Move Semantics for Smart Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
15.4.1 Move Semantics for std::shared_ptr<> . . . . . . . . . . . . . . . . . . . . . . . . 224
15.4.2 Move Semantics for std::unique_ptr<> . . . . . . . . . . . . . . . . . . . . . . . . 225
15.5 Move Semantics for IOStreams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
15.5.1 Moving IOStream Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
15.5.2 Using Temporary IOStreams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
15.6 Move Semantics for Multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
15.6.1 std::thread<> and std::jthread<> . . . . . . . . . . . . . . . . . . . . . . . . . . 229
15.6.2 Futures, Promises, and Packaged Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . 230
15.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232

Glossary 233

Index 237
Josuttis: C++ Move Semantics 2022/04/19 13:28 page x
Josuttis: C++ Move Semantics 2022/04/19 13:28 page xi

Preface

Move semantics, introduced with C++11, has become a hallmark of modern C++ programming. However, it
also complicates the language in many ways. Even after several years of support, experienced programmers
struggle with all the details of move semantics, style guides still recommend different consequences for
programming even of trivial classes, and we still discuss semantic details in the C++ standards committee.
Whenever I have taught what I have learned about C++ move semantics so far, I have said, “Somebody
has to write a book about all this,” and the usual answer was: “Yes, please do!” So, I finally did.
As always when writing a book about C++, I was surprised about the number of aspects to be taught, the
situations to be clarified, and the consequences to be described. It really was time to write a book about all
aspects of move semantics, covering all C++ versions from C++11 up to C++20. I learned a lot and I am
sure you will too.

An Experiment
This book is an experiment in two ways:
• I am writing an in-depth book covering a complex core language feature without the direct help of a core
language expert as a co-author. However, I can ask questions and I do.
• I am publishing the book myself on Leanpub and for printing on demand. That is, this book is written
step by step and I will publish new versions as soon there is a significant improvement that makes the
publication of a new version worthwhile.
The good thing is:
• You get the view of the language features from an experienced application programmer—somebody who
feels the pain a feature might cause and asks the relevant questions to be able to motivate and explain the
design and its consequences for programming in practice.
• You can benefit from my experience with move semantics while I am still writing.
• This book and all readers can benefit from your early feedback.
This means that you are also part of the experiment. So help me out: give feedback about flaws, errors,
features that are not explained well, or gaps, so that we all can benefit from these improvements.

xi
Josuttis: C++ Move Semantics 2022/04/19 13:28 page xii

xii Preface

Versions of This Book


Because this book is written incrementally, the following is a history of the major updates (newest first):
• 2020-10-27: Several fixes (see errata)
• 2020-09-18: Using lambdas with template parameters (since C++20)
• 2020-09-15: Fix a bug with full specializations of universal references
• 2020-09-12: std::move() for data members
• 2020-09-10: Fixing deferred perfect returning
• 2020-09-09: Proof reading done and final fixes to go into print
• 2020-09-06: Helper trait is_nothrow_movable for abstract base classes
• 2020-09-06: Value category of (references to) functions
• 2020-09-05: Clarifications on auto&& including using it in C++20 functions
• 2020-08-29: Move assignments of objects to themselves
• 2020-08-28: Move semantics for std::pair<>, std::optional<>, threads, etc.
• 2020-08-28: Unique pointers, IOStreams, and other move-only types
• 2020-08-26: Several clarifications about universal references
• 2020-08-25: Using std::move() when calling member functions
• 2020-08-20: New chapter about move-only types
• 2020-08-19: Discussion of noexcept details
• 2020-08-18: New chapter about moving algorithms and iterators
• 2020-08-10: Description of move semantics for shared pointers
• 2020-08-10: Motivation for the reuse of moved-from objects and clarification of move assignments of
objects to themselves
• 2020-08-09: Recommendation not to return by value with const
• 2020-07-27: Move semantics for strings and containers
• 2020-07-24: General remarks on using reference qualifiers
• 2020-07-23: Description of details of type deduction of universal references and reference collapsing for
perfect forwarding
• 2020-07-07: Description of perfect returning for lambdas
• 2020-06-21: New chapter about perfect returning (with small fixes for perfect forwarding)
• 2020-06-12: Improvements of the chapter about “invalid” states
• 2020-06-08: New chapter about using noexcept
• 2020-06-06: Improvements of the chapter about invalid states
• 2020-05-03: Fixing of move semantics in class hierarchies
• 2020-04-29: Fixing of move semantics for classes and invalid states after review
• 2020-04-25: Fixing of code layout and missing figures in non-PDF versions
• 2020-04-22: New chapter about moved-from states
• 2020-04-13: Discussion of when you cannot avoid using std::move()
• 2020-02-01: Discussion of when automatically generated move operations are broken
• 2020-01-19: Constructors with universal references
Josuttis: C++ Move Semantics 2022/04/19 13:28 page xiii

Acknowledgments xiii

• 2020-01-04: The initial published version of the book

Acknowledgments
First of all, I would like to thank you, the C++ community, for making this book possible. The incredible
design of all the features of move semantics, the helpful feedback, and their curiosity are the basis for the
evolution of a successful language. In particular, thanks for all the issues you told me about and explained
and for the feedback you gave.
I would especially like to thank everyone who reviewed drafts of this book or corresponding slides and
provided valuable feedback and clarification. These reviews increased the quality of the book significantly,
again proving that good things need the input of many “wise guys.” Therefore, so far (this list is still
growing) huge thanks to Javier Estrada, Howard Hinnant, Klaus Iglberger, Daniel Krügler, Marc Mutz,
Aleksandr Solovev (alexolut), Peter Sommerlad, and Tony Van Eerd.
In addition, I would like to thank everyone in the C++ community and on the C++ standards committee.
In addition to all the work involved in adding new language and library features, these experts spent many,
many hours explaining and discussing their work with me, and they did so with patience and enthusiasm.
Special thanks go to the LaTeX community for a great text system and to Frank Mittelbach for solving
my LATEX issues (it was almost always my fault).
And finally, many thanks go to my proofreader, Tracey Duffy, who has done a tremendous job of con-
verting my “German English” into native English.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page xiv

xiv

This page is intentionally left blank


Josuttis: C++ Move Semantics 2022/04/19 13:28 page xv

About This Book

This book teaches C++ move semantics. Starting from the basic principles, it motivates and explains all
features and corner cases of move semantics so that as a programmer, you can understand and use move
semantics correctly. The book is valuable for those who are just starting to learn about move semantics and
is essential for those who are using it already.
As usual for my books, the focus lies on the application of the new features in practice and the book will
demonstrate how features impact day-to-day programming and how you can benefit from them in projects.
This applies to both application programmers and programmers who provide generic frameworks and foun-
dation libraries.

What You Should Know Before Reading This Book


To get the most from this book, you should already be familiar with C++. You should be familiar with
the concepts of classes and references in general, and you should be able to write C++ programs using
components such as IOStreams and containers from the C++ standard library. You should also be familiar
with the basic features of “Modern C++,” such as auto or the range-based for loop.
However, you do not have to be an expert. My goal is to make the content understandable for the average
C++ programmer who does not necessarily know all the details of the latest features. I will discuss basic
features and review more subtle issues as the need arises.
This ensures that the text is accessible to experts and intermediate programmers alike.

Overall Structure of the Book


This book covers all aspects of C++ move semantics up to C++20. This applies to both language and
library features as well as both features that affect day-to-day application programming and features for
the sophisticated implementation of (foundation) libraries. However, the more general cases and examples
usually come first.
The different chapters are grouped, so that didactically you should read the book from beginning to end.
That is, later chapters usually rely on features introduced in earlier chapters. However, cross-references also
help in specific subsequent topics, indicating where they refer to features and aspects introduced earlier.

xv
Josuttis: C++ Move Semantics 2022/04/19 13:28 page xvi

xvi About This Book

The book therefore contains the following parts:


• Part I covers the basic features of move semantics (especially for non-generic code).
• Part II covers the features of move semantics for generic code (especially used in templates and generic
lambdas).
• Part III covers the use of move semantics in the C++ standard library (giving also a good example of
how to use move semantics in practice).

How to Read This Book


Do not be afraid by the number of pages in this book. As always with C++, things can become pretty
complicated when you look into details (such as implementing templates). For a basic understanding, the
first third of the book (Part I, especially chapters 1 to 5) is sufficient.
In my experience, the best way to learn something new is to look at examples. Therefore, you will find
a lot of examples throughout the book. Some are just a few lines of code illustrating an abstract concept,
whereas others are complete programs that provide a concrete application of the material. The latter kind of
examples will be introduced by a C++ comment describing the file containing the program code. You can
find these files on the website for this book at http://www.cppmove.com.

The Way I Implement


Note the following hints about the way I write code and comments.

Initializations
I usually use the modern form of initialization (introduced in C++11 as uniform initialization) with curly
braces:
int i{42};
std::string s{"hello"};
This form of initialization, which is called brace initialization, has the following advantages:
• It can be used with fundamental types, class types, aggregates, enumeration types, and auto
• It can be used to initialize containers with multiple values
• It can detect narrowing errors (e.g., initialization of an int by a floating-point value)
• It cannot be confused with function declarations or calls
If the braces are empty, the default constructors of (sub)objects are called and fundamental data types are
guaranteed to be initialized with 0/false/nullptr.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page xvii

The C++ Standards xvii

Error Terminology
I often talk about programming errors. If there is no special hint, the term error or a comment such as
... // ERROR
means a compile-time error. The corresponding code should not compile (with a conforming compiler).
If I use the term runtime error, the program might compile but not behave correctly or result in undefined
behavior (thus, it might or might not do what is expected).

Code Simplifications
I try to explain all features with helpful examples. However, to concentrate on the key aspects to be taught,
I might often skip other details that should be part of code.
• Most of the time I use an ellipsis (“...”) to signal additional code that is missing. Note that I do not use
code font here. If you see an ellipsis with code font, code must have these three dots as a language feature
(such as for “typename...”).
• In header files I usually skip the preprocessor guards. All header files should have something like the
following:
#ifndef MYFILE_HPP
#define MYFILE_HPP
...
#endif // MYFILE_HPP
So, please beware and fix the code when using these header files in your projects.

The C++ Standards


C++ has different versions defined by different C++ standards.
The original C++ standard was published in 1998 and was subsequently amended by a technical corri-
gendum in 2003, which provided minor corrections and clarifications to the original standard. This “old C++
standard” is known as C++98 or C++03.
The world of “Modern C++” began with C++11 and was extended with C++14 and C++17. The interna-
tional C++ standards committee now aims to issue a new standard every three years. Clearly, that leaves less
time for massive additions, but it brings the changes to the broader programming community more quickly.
The development of larger features, therefore, takes time and might cover multiple standards.
The next “Even more Modern C++” is already on the horizon, as introduced with C++20. Again, several
ways to program will probably change. However, as usual, compilers need some time to provide the latest
language features. At the time of writing this book, C++17 is usually the latest version supported by major
compilers.
Fortunately, the basic principles of move semantics were all introduced with C++11 and C++14. For that
reason, the code examples in this book should usually compile on recent versions of all major compilers. If
special features introduced with C++17 or C++20 are discussed, I will mention that explicitly.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page xviii

xviii About This Book

Example Code and Additional Information


You can access all example programs and find more information about this book from its website, which has
the following URL:
http://www.cppmove.com

Feedback
I welcome your constructive input—both negative and positive. I have worked very hard to bring you what
I hope you will find to be an excellent book. However, at some point I had to stop writing, reviewing, and
tweaking to “release the new revision.” You may therefore find errors, inconsistencies, presentations that
could be improved, or topics that are missing altogether. Your feedback gives me a chance to fix these issues,
inform all readers about the changes through the book’s website, and improve any subsequent revisions or
editions.
The best way to reach me is by email. You will find the email address at the website for this book:
http://www.cppmove.com

If you use the ebook, you might want to ensure to have the latest version of this book available (remember
it is written and published incrementally). You should also check the book’s Web site for the currently
known errata before submitting reports. In any case, refer to the publishing date of this version when giving
feedback. The current publishing date is 2022-04-19 (you can also find it on page ii, the page directly after
the cover).
Many thanks.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 1

Part I
Basic Features of Move Semantics
This part of the book introduces the basic features of move semantics that are not specific to generic pro-
gramming (i.e., templates). They are particularly helpful for application programmers in their day-to-day
programming and therefore every C++ programmer using Modern C++ should know them.
Move semantics features for generic programming are covered in Part II.

1
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 2

This page is intentionally left blank


Josuttis: C++ Move Semantics 2022/04/19 13:28 page 3

Chapter 1
The Power of Move Semantics

This chapter demonstrates the basic principles and benefits of move semantics using a short code example.

1.1 Motivation for Move Semantics


To understand the basic principles of move semantics, let us look at the execution of a small piece of code,
first without move semantics (i.e., compiled with an old C++ compiler that supports only C++03) and then
with move semantics (compiled with a modern C++ compiler that supports C++11 or later).

1.1.1 Example with C++03 (Before Move Semantics)


Assume we have the following program:
basics/motiv03.cpp
 
#include <string>
#include <vector>

std::vector<std::string> createAndInsert()
{
std::vector<std::string> coll; // create vector of strings
coll.reserve(3); // reserve memory for 3 elements
std::string s = "data"; // create string object

coll.push_back(s); // insert string object


coll.push_back(s+s); // insert temporary string
coll.push_back(s); // insert string

return coll; // return vector of strings


}

3
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 4

4 Chapter 1: The Power of Move Semantics

int main()
{
std::vector<std::string> v; // create empty vector of strings
...
v = createAndInsert(); // assign returned vector of strings
...
}
 
Let us look at the individual steps of the program (inspecting both the stack and the heap) when we compile
this program with a C++ compiler that does not support move semantics.
• First, in main(), we create the empty vector v:
std::vector<std::string> v;
which is placed on the stack as an object that has 0 as the number of elements and no memory allocated
for elements.
• Then, we call
v = createAndInsert();
where we create another empty vector coll on the stack and reserve memory for three elements on the
heap:
std::vector<std::string> coll;
coll.reserve(3);
The allocated memory is not initialized because the number of elements is still 0.
• Then, we create a string initialized with "data":
std::string s = "data";
A string is something like a vector with char elements. Essentially, we create an object on the stack
with a member for the number of characters (having the value 4) and a pointer to the memory for the
characters.1
After this statement, the program has the following state: we have three objects on the stack: v, coll,
and s. Two of them, coll and s, have allocated memory on the heap:2

1 Internally, strings also store a terminating null character to avoid allocating memory when they are asked for a C
string representation of their value with the member function c_str().
2 With the small string optimization (SSO), the string s might store its whole value on the stack provided the value is
not too long. However, for the general case, let us assume that we do not have the small string optimization or the
value of the string is long enough so that the small string optimization does not happen.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 5

1.1 Motivation for Move Semantics 5

• The next step is the command to insert the string into the vector coll:
coll.push_back(s);
All containers in the C++ standard library have value semantics, which means that they create copies of
the values passed to them. As a result, we get a first element in the vector, which is a full (deep) copy of
the passed value/object s:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 6

6 Chapter 1: The Power of Move Semantics

So far, we have nothing to optimize in this program. The current state is that we have two vectors, v and
coll, and two strings, s and its copy, which is the first element in coll. They should all be separate
objects with their own memory for the value, because modifying one of them should not impact any of
the other objects.
• Let us now look at the next statement, which creates a new temporary string and again inserts it into the
vector:
coll.push_back(s+s);
This statement is performed in three steps:
1. We create the temporary string s+s:

2. We insert this temporary string into the vector coll. As always, the container creates a copy of the
passed value, which means that we create a deep copy of the temporary string, including allocating
memory for the value:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 7

1.1 Motivation for Move Semantics 7

3. At the end of the statement, the temporary string s+s is destroyed because we no longer need it:

Here, we have the first moment where we generate code that is not performing well: we create a copy
of a temporary string and destroy the source of the copy immediately afterwards, which means that we
unnecessarily allocate and free memory that we could have just moved from the source to the copy.
• With the next statement, again we insert s into coll:
coll.push_back(s);
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 8

8 Chapter 1: The Power of Move Semantics

Again, coll copies s:

This is also something to improve: because the value of s is no longer needed some optimization could
use the memory of s as memory for the new element in the vector instead.
• At the end of createAndInsert() we come to the return statement:
return coll;
}
Here, the behavior of the program becomes a bit more complicated. We return by value (the return type
is not a reference), which should be a copy of the value in the return statement, coll. Creating a copy
of coll means that we have to create a deep copy of the whole vector with all of its elements. Thus, we
have to allocate heap memory for the array of elements in the vector and heap memory for the value each
string allocates to hold its value. Here, we would have to allocate memory 4 times.
However, since at the same time coll is destroyed because we leave the scope where it is declared,
the compiler is allowed to perform the named return value optimization (NRVO). This means that the
compiler can generate code so that coll is just used as the return value.
This optimization is allowed even if this would change the functional behavior of the program. If we
had a print statement in the copy constructor of a vector or string, we would see that the program no
longer has the output from the print statement. This means that this optimization changes the functional
behavior of the program. However, that is OK, because we explicitly allow this optimization in the C++
standard even if it has side effects. Nobody should expect that a copy is done here, in the same way that
nobody should expect that it is not, either. It is simply up to the compiler whether the named return value
optimization is performed.
Let us assume that we have the named return value optimization. In that case, at the end of the return
statement, coll now becomes the return value and the destructor of s is called, which frees the memory
allocated when it was declared:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 9

1.1 Motivation for Move Semantics 9

• Finally, we come to the assignment of the return value to v:


v = createAndInsert();
Here, we really get behavior that can be improved: the usual assignment operator has the goal of giving v
the same value as the source value that is assigned. In general, any assigned value should not be modified
and should be independent from the object that the value was assigned to. So, the assignment operator
will create a deep copy of the whole return value:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 10

10 Chapter 1: The Power of Move Semantics

However, right after that, we no longer need the temporary return value and we destroy it:

Again, we create a copy of a temporary object and destroy the source of the copy immediately after-
wards, which means that we again unnecessarily allocate and free memory. This time it applies to four
allocations, one for the vector and one for each string element.
For the state of this program after the assignment in main(), we allocated memory ten times and released it
six times. The unnecessary memory allocations were caused by:
• Inserting a temporary object into the collection
• Inserting an object into the collection where we no longer need the value
• Assigning a temporary vector with all its elements
We can more or less avoid these performance penalties. In particular, instead of the last assignment, we
could do the following:
• Pass the vector as an out parameter:
createAndInsert(v); // let the function fill vector v
• Use swap():
createAndInsert().swap(v);
However, the resulting code looks uglier (unless you see some beauty in complex code) and there is not
really a workaround when inserting a temporary object.
Since C++11, we have another option: compile and run the program with support for move semantics.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 11

1.1 Motivation for Move Semantics 11

1.1.2 Example Since C++11 (Using Move Semantics)


Let us now recompile the program with a modern C++ compiler (C++11 or later) that supports move se-
mantics:
basics/motiv11.cpp
 
#include <string>
#include <vector>

std::vector<std::string> createAndInsert()
{
std::vector<std::string> coll; // create vector of strings
coll.reserve(3); // reserve memory for 3 elements
std::string s = "data"; // create string object

coll.push_back(s); // insert string object


coll.push_back(s+s); // insert temporary string
coll.push_back(std::move(s)); // insert string (we no longer need the value of s)

return coll; // return vector of strings


}

int main()
{
std::vector<std::string> v; // create empty vector of strings
...
v = createAndInsert(); // assign returned vector of strings
...
}
 
There is a small modification, though: we add a std::move() call when we insert the last element into
coll. We will discuss this change when we come to this statement. Everything else is as before.
Again, let us look at the individual steps of the program by inspecting both the stack and the heap.
• First, in main(), we create the empty vector v, which is placed on the stack with 0 elements:
std::vector<std::string> v;
• Then, we call
v = createAndInsert();
where we create another empty vector coll on the stack and reserve uninitialized memory for three
elements on the heap:
std::vector<std::string> coll;
coll.reserve(3);
• Then, we create the string s initialized with "data" and insert it into coll again:
std::string s = "data";
coll.push_back(s);
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 12

12 Chapter 1: The Power of Move Semantics

So far, there is nothing to optimize and we get the same state as with C++03:

We have two vectors, v and coll, and two strings, s and its copy, which is the first element in coll.
They should all be separate objects with their own memory for the value, because modifying one of them
should not impact any of the other objects.
• This is where things change. First, let us look at the statement that creates a new temporary string and
inserts it into the vector:
coll.push_back(s+s);
Again, this statement is performed in three steps:
1. We create the temporary string s+s:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 13

1.1 Motivation for Move Semantics 13

2. We insert this temporary string into the vector coll. However, here something different happens now:
we steal the memory for the value from s+s and move it to the new element of coll.

This is possible because since C++11, we can implement special behavior for getting a value that is
no longer needed. The compiler can signal this fact because it knows that right after performing the
push_back() call, the temporary object s+s will be destroyed. So, we call a different implementation
of push_back() provided for the case when the caller no longer needs that value. As we can see, the
effect is an optimized implementation of copying a string where we no longer need the value: instead
of creating an individual deep copy, we copy both the size and the pointer to the memory. However,
that shallow copy is not enough; we also modify the temporary object s+s by setting the size to 0 and
assigning the nullptr as new value. Essentially, s+s is modified so that it gets the state of an empty
string. The important point is that it no longer owns its memory. And that is important because we
still have a third step in this statement.
3. At the end of the statement, the temporary string s+s is destroyed because we no longer need it.
However, because the temporary string is no longer the owner of the initial memory, the destructor
will not free this memory.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 14

14 Chapter 1: The Power of Move Semantics

Essentially, we optimize the copying so that we move the ownership of the memory for the value of s+s
to its copy in the vector.
This is all done automatically by using a compiler that can signal that an object is about to die, so that
we can use new implementations to copy a string value that steals the value from the source. It is not a
technical move; it is a semantic move implemented by technically moving the memory for the value from
the source string to its copy.
• The next statement is the statement we modified for the C++11 version. Again, we insert s into coll,
but the statement has changed by calling std::move() for the string s that we insert:
coll.push_back(std::move(s));
Without std::move(), the same would happen as with the first call of push_back(): the vector would
create a deep copy of the passed string s. However, in this call, we have marked s with std::move(),
which semantically means “I no longer need this value here.” As a consequence, we have another call of
the other implementation of push_back(), which was used when we passed the temporary object s+s.
The third element steals the value by moving the ownership of the memory for the value from s to its
copy:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 15

1.1 Motivation for Move Semantics 15

Note the following two very important things to understand about move semantics:
– std::move(s) only marks s to be movable in this context. It does not move anything. It only says,
“I no longer need this value here.” It allows the implementation of the call to benefit from this mark
by performing some optimization when copying the value, such as stealing the memory. Whether the
value is moved is something the caller does not know.
– However, an optimization that steals the value has to ensure that the source object is still in a valid state.
A moved-from object is neither partially nor fully destroyed. The C++ standard library formulates this
for its types as follows: after an operation called for an object marked with std::move(), the object
is in a valid but unspecified state.
That is, after calling
coll.push_back(std::move(s));
it is guaranteed that s is still a valid string. You can do whatever you want as long as it is valid for
any string where you do not know the value. It is like using a string parameter where you do not know
which value was passed.
Note that it is also not guaranteed that the string either has its old value or is empty. The value it
has is up to the implementers of the (library) function. In general, implementers can do with objects
marked with std::move() whatever they like, provided they leave the object in a valid state. There
are good reasons for this guarantee, which will be discussed later.

• Again, at the end of createAndInsert() we come to the return statement:


return coll;
}
It is still up to the compiler whether it generates code with the named return value optimization, which
would mean that coll just becomes the return value. However, if this optimization is not used, the return
statement is still cheap, because again we have a situation where we create an object from a source that
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 16

16 Chapter 1: The Power of Move Semantics

is about to die. That is, if the named return value optimization is not used, move semantics will be used,
which means that the return value steals the value from coll. At worst, we have to copy the members
for size, capacity, and the pointer to the memory (in total, usually 12 or 24 bytes) from the source to the
return value and assign new values to these members in the source.
Let us assume that we have the named return value optimization. In that case, at the end of the return
statement, coll now becomes the return value and the destructor of s is called, which no longer has to
free any memory because it was moved to the third element of coll:

• So, finally, we come to the assignment of the return value to v:


v = createAndInsert();
Again, we can benefit from move semantics now because we have a situation we have already seen: we
have to copy (here, assign) a value from a temporary return value that is about to die.
Now, move semantics allows us to provide a different implementation of the assignment operator for
a vector that just steals the value from the source vector:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 17

1.1 Motivation for Move Semantics 17

Again, the temporary object is not (partially) destroyed. It enters into a valid state but we do not know its
value.
However, right after the assignment, the end of the statement destroys the (modified) temporary return
value:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 18

18 Chapter 1: The Power of Move Semantics

At the end we are in the same state as before using move semantics but something significant has changed:
we saved six allocations and releases of memory. All unnecessary memory allocations no longer took place:
• Allocations for inserting a temporary object into the collection
• Allocations for inserting a named object into the collection, when we use std::move() to signal that we
no longer need the value
• Allocations for assigning a temporary vector with all its elements
In the second case, the optimization was done with our help. By adding std::move(), we had to say that
we no longer needed the value of s there. All other optimizations happened because the compiler knows that
an object is about to die, meaning that it can call the optimized implementation, which uses move semantics.
This means that returning a vector of strings and assigning it to an existing vector is no longer a perfor-
mance issue. We can use a vector of strings naively like an integral type and get much better performance.
In practice, recompiling code with move semantics can improve speed by 10% to 40% (depending on how
naive the existing code was).

1.2 Implementing Move Semantics


Let us use the previous example to see where and how move semantics is implemented.
Before move semantics was implemented, class std::vector<> had only one implementation of push_back()
(the declaration of vector is simplified here):
template<typename T>
class vector {
public:
...
// insert a copy of elem:
void push_back (const T& elem);
...
};
There was only one way to pass an argument to push_back() binding it to a const reference. push_back()
is implemented in a way that the vector creates an internal copy of the passed argument without modifying
it.
Since C++11, we have a second overload of push_back():
template<typename T>
class vector {
public:
...
// insert a copy of elem:
void push_back (const T& elem);

// insert elem when the value of elem is no longer needed:


void push_back (T&& elem);
...
};
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 19

1.2 Implementing Move Semantics 19

The second push_back() uses a new syntax introduced for move semantics. We declare the argument with
two & and without const. Such an argument is called an rvalue reference.3 “Ordinary references” that
have only one & are now called lvalue references. That is, in both calls we pass the value to be inserted by
reference. However, the difference is as follows:
• With push_back(const T&), we promise not to modify the passed value.
This function is called when the caller still needs the passed value.
• With push_back(T&&), the implementation can modify the passed argument (therefore it is not const)
to “steal” the value. The semantic meaning is still that the new element receives the value of the passed
argument but we can use an optimized implementation that moves the value into the vector.
This function is called when the caller no longer needs the passed value. The implementation has to
ensure that the passed argument is still in a valid state. However, the value may be changed. Therefore,
after calling this, the caller can still use the passed argument as long as the caller does not make any
assumption about its value.
However, a vector does not know how to copy or move an element. After making sure that the vector has
enough memory for the new element, the vector delegates the work to the type of the elements.
In this case, the elements are strings. So, let us see what happens if we copy or move the passed string.

1.2.1 Using the Copy Constructor


push_back(const T&) for the traditional copy semantics calls the copy constructor of the string class,
which initializes the new element in the vector. Let us look at how this is implemented. The copy constructor
of a very naive implementation of a string class would look like this:4
class string {
private:
int len; // current number of characters
char* data; // dynamic array of characters

public:
// copy constructor: create a full copy of s:
string (const string& s)
: len{s.len} { // copy number of characters
if (len > 0) { // if not empty
data = new char[len+1]; // - allocate new memory
memcpy(data, s.data, len+1); // - and copy the characters
}
}
...
};
Given that we call this copy constructor for a string that has the value "data":

3 The reason this is called an rvalue reference is discussed later in the chapter about value categories.
4 The implementation of class std::string is more complicated because for its internal memory management it uses
optimizations and allocators (helper objects that define the way to allocate memory).
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 20

20 Chapter 1: The Power of Move Semantics

std::string a = "data";
std::string b = a; // create b as a copy of a
after initializing the string a as follows:

the copy constructor above would copy the member len for the number of characters but assign new memory
for the value to the data pointer and copy all characters from the source a (passed as s) to the new string:

1.2.2 Using the Move Constructor


push_back(T&&) for the new move semantics calls a corresponding new constructor, the move constructor.
This is the constructor that creates a new string from an existing string, where the value is no longer needed.
As usual with move semantics, the constructor is declared with a non-const rvalue reference (&&) as its
parameter:
class string {
private:
int len; // current number of characters
char* data; // dynamic array of characters

public:
...
// move constructor: initialize the new string from s (stealing the value):
string (string&& s)
: len{s.len}, data{s.data} { // copy number of characters and pointer to memory
s.data = nullptr; // release the memory for the source value
s.len = 0; // and adjust number of characters accordingly
}
...
};
Given the situation from the copy constructor above:
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 21

1.3 Copying as a Fallback 21

we can call this constructor for a string as follows:


std::string c = std::move(b); // init c with the value of b (no longer needing its value here)
The move constructor first copies both the members len and data, meaning that the new string gets owner-
ship of the value of b (passed as s).

However, this is not enough, because the destructor of b would free the memory. Therefore, we also modify
the source string to lose its ownership of the memory and bring it into a consistent state representing the
empty string:

The effect is that c now has the former value of b and that b is the empty string. Again, note that the
only guarantee is that b is subsequently in a valid but unspecified state. Depending on the way the move
constructor is implemented in a C++ library, it might not be empty (but it usually is because this is the easiest
and best way to improve performance here).

1.3 Copying as a Fallback


We saw that by using temporary objects or marking objects with std::move() we can enable move seman-
tics. Functions providing special implementations (by taking non-const rvalue references) can optimize the
copying of a value by “stealing” the value from the source. However, if there is no optimized version of a
function for move semantics, then the usual copying is used as a fallback.
For example, assume a container class like vector lacks the second overload of push_back():
template<typename T>
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 22

22 Chapter 1: The Power of Move Semantics

class MyVector {
public:
...
void push_back (const T& elem); // insert a copy of elem
... // no other push_back() declared
};
We can still pass a temporary object or an object marked with std::move():
MyVector<std::string> coll;
std::string s{"data"};
...
coll.push_back(std::move(s)); // OK, uses copy semantics
The rule is that for a temporary object or an object marked with std::move(), if available, a function
declaring the parameter as an rvalue reference is preferred. However, if no such function exists, the usual
copy semantics is used. That way, we ensure that the caller does not have to know whether an optimization
exists. The optimization might not exist because:
• The function/class was implemented before move semantics was supported or without having move se-
mantics support in mind
• There is nothing to optimize (a class with only numeric members would be an example of that)
For generic code, it is important that we can always mark an object with std::move() if we no longer need
its value. The corresponding code compiles even if there is no move semantics support.
For the same reason, you can even mark objects of a fundamental data type such as int (or a pointer)
with std::move(). The usual value semantics copying the value (the address) will still be used:
std::vector<int> coll;
int x{42};
...
coll.push_back(std::move(x)); // OK, but copies x (std::move() has no effect)

1.4 Move Semantics for const Objects


Finally, note that objects declared with const cannot be moved because any optimizing implementation
requires that the passed argument can be modified. We cannot steal a value if we are not allowed to modify
it.
With the usual overloads of push_back():
template<typename T>
class vector {
public:
...
// insert a copy of elem:
void push_back (const T& elem);

// insert elem when the value of elem is no longer needed:


void push_back (T&& elem);
...
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 23

1.5 Summary 23

};
the only valid function to call for const objects is the first overload of push_back() with the const&
parameter:
std::vector<std::string> coll;
const std::string s{"data"};
...
coll.push_back(std::move(s)); // OK, calls push_back(const std::string&)
That means that a std::move() for const objects essentially has no effect.
In principle, we could provide a special overload for this case by declaring a function taking a const
rvalue reference. However, this makes no semantic sense. Again, the const lvalue reference overload
serves as a fallback to handle this case.

1.4.1 const Return Values


The fact that const disables move semantics also has consequences for declaring return types. A const
return value cannot be moved.
Therefore, since C++11, it is no longer good style to return by value with const (as some style guides
have recommended in the past). For example:
const std::string getValue();

std::vector<std::string> coll;
...
coll.push_back(getValue()); // copies (because the return value is const)
When returning by value, do not declare the return value as a whole to be const. Use const only to declare
parts of your return type (such as the object a returned reference or pointer refers to):
const std::string getValue(); // BAD: disables move semantics for return values
const std::string& getRef(); // OK
const std::string* getPtr(); // OK

1.5 Summary
• Move semantics allows us to optimize the copying of objects, where we no longer need the value. It can be
used implicitly (for unnamed temporary objects or local return values) or explicitly (with std::move()).
• std::move() means I no longer need this value here. It marks the object as movable. An object marked
with std::move() is not (partially) destroyed (the destructor still will be called).
• By declaring a function with a non-const rvalue reference (such as std::string&&), you define an
interface where the caller semantically claims that it no longer needs the passed value. The implementer
of the function can use this information to optimize its task by “stealing” the value or do any other
modification with the passed argument. Usually, the implementer also has to ensure that the passed
argument is in a valid state after the call.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 24

24 Chapter 1: The Power of Move Semantics

• Moved-from objects of the C++ standard library are still valid objects, but you no longer know their
value.
• Copy semantics is used as a fallback for move semantics (if copy semantics is supported). If there is no
implementation taking an rvalue reference, any implementation taking an ordinary const lvalue reference
(such as const std::string&) is used. This fallback is then used even if the object is explicitly marked
with std::move().
• Calling std::move() for a const object usually has no effect.
• If you return by value (not by reference), do not declare the return value as a whole to be const.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 25

Chapter 2
Core Features of Move Semantics

After the first motivating example, this chapter discusses the basic features of move semantics.

2.1 Rvalue References


To support move semantics we introduce a new type of reference: rvalue references. Let us discuss what
they are and how to use them.

2.1.1 Rvalue References in Detail


Rvalue references are declared with two ampersands. Just as ordinary references, which are declared with
one ampersand and are now called lvalue references, rvalue references refer to an existing object that has
to be passed as an initial value. However, according to their semantic meaning, rvalue references can refer
only to a temporary object that does not have a name or to an object marked with std::move():
std::string returnStringByValue(); // forward declaration
...
std::string s{"hello"};
...
std::string&& r1{s}; // ERROR
std::string&& r2{std::move(s)}; // OK
std::string&& r3{returnStringByValue()}; // OK, extends lifetime of return value
The name rvalue reference comes from the fact that these objects can usually refer only to rvalues, a value
category for temporary objects that do not have a name and objects marked with std::move().
As usual for successful initializations of references from return values, references extend the lifetime of
the return value until the end of the lifetime of the reference (ordinary const lvalue references already had
this behavior).
The syntax used to initialize the reference is irrelevant. You can use the equal sign, braces, or parenthe-
ses:

25
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 26

26 Chapter 2: Core Features of Move Semantics

std::string s{"hello"};
...
std::string&& r1 = std::move(s); // OK, rvalue reference to s
std::string&& r2{std::move(s)}; // OK, rvalue reference to s
std::string&& r3(std::move(s)); // OK, rvalue reference to s
All these references have the semantics of “we can steal/modify the object we refer to, provided the state
of the object remains a valid state.” Technically, these semantics are not checked by compilers, so we can
modify an rvalue reference as we can do with any non-const object of the type. We might also decide not
to modify the value. That is, if you have an rvalue reference to an object, the object might receive a different
value (which might or might not be the value of a default-constructed object) or it might keep its value.
As we have seen, move semantics allows us to optimize using a value of a source that no longer needs the
value. If compilers automatically detect that a value is used from an object that is at the end of its lifetime,
they will automatically switch to move semantics. This is the case when:
• We pass the value of a temporary object that will automatically be destroyed after the statement.
• We pass a non-const object marked with std::move().

2.1.2 Rvalue References as Parameters


When we declare a parameter to be an rvalue reference, it has exactly the behavior and semantics as intro-
duced above:
• The parameter can bind only to a temporary object that does not have a name or to an object marked with
std::move().
• According to the semantics of rvalue references:
– The caller claims that it is no longer interested in the value. Therefore, you can modify the object the
parameter refers to.
– However, the caller might still be interested in using the object. Therefore, any modification should
keep the referenced object in a valid state.
For example:
void foo(std::string&& rv); // takes only objects where we no longer need the value
...
std::string s{"hello"};
...
foo(s); // ERROR
foo(std::move(s)); // OK, value of s might change
foo(returnStringByValue()); // OK
You can use a named object after passing it with std::move() but usually you should not. The recom-
mended programming style is to no longer use an object after a std::move():
void foo(std::string&& rv); // takes only objects where we no longer need the value
...
std::string s{"hello"};
...
foo(std::move(s)); // OK, value of s might change
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 27

2.2 std::move() 27

std::cout << s << '\n'; // OOPS, you don’t know which value is printed
foo(std::move(s)); // OOPS, you don’t know which value is passed
s = "hello again"; // OK, but rarely done
foo(std::move(s)); // OK, value of s might change
For both lines marked with “OOPS,” the call is technically OK as long as you make no assumption about
the current value of s. Printing out the value is therefore fine, although usually not very useful.

2.2 std::move()
If you have an object for which the lifetime does not end when you use it, you can mark it with std::move()
to express “I no longer need this value here.” std::move() does not move; it only sets a temporary marker
in the context where the expression is used:
void foo1(const std::string& lr); // binds to the passed object without modifying it
void foo1(std::string&& rv); // binds to the passed object and might steal/modify the value
...
std::string s{"hello"};
...
foo1(s); // calls the first foo1(), s keeps its value
foo1(std::move(s)); // calls the second foo1(), s might lose its value
Objects marked with std::move() can still be passed to a function that takes an ordinary const lvalue
reference:
void foo2(const std::string& lr); // binds to the passed object without modifying it
... // no other overload of foo2()
std::string s{"hello"};
...
foo2(s); // calls foo2(), s keeps its value
foo2(std::move(s)); // also calls foo2(), s keeps its value
Note that an object marked with std::move() cannot be passed to a non-const lvalue reference:
void foo3(std::string&); // modifies the passed argument
...
std::string s{"hello"};
...
foo3(s); // OK, calls foo3()
foo3(std::move(s)); // ERROR: no matching foo3() declared
Note that it does not make sense to mark a dying object with std::move(). In fact, this can even be
counterproductive for optimizations.

2.2.1 Header File for std::move()


std::move() is defined as a function in the C++ standard library. Therefore, to use it, you have to include
the header file <utility> where it is defined:
#include <utility> // for std::move()
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 28

28 Chapter 2: Core Features of Move Semantics

Programs using std::move() usually compile without including this header file, because in practice almost
all header files include <utility>. However, no standard header file is required to include utility.
Therefore, when using std::move(), you should explicitly include <utility> to make your program
portable.

2.2.2 Implementation of std::move()


std::move() is nothing but a static_cast to an rvalue reference. You can achieve the same effect by
calling static_cast manually as follows:
foo(static_cast<decltype(obj)&&>(obj)); // same effect as foo(std::move(obj))
Therefore, we could also write:
std::string s;
...
foo(static_cast<std::string&&>(s)); // same effect as foo(std::move(s))
Note that the static_cast does a bit more than only changing the type of the object here. It also enables
the object to be passed to an rvalue reference (remember that passing objects with names to rvalue references
is usually not allowed). We will discuss this in detail in the chapter about value categories.

2.3 Moved-From Objects


After a std::move(), moved-from objects are not (partially) destroyed. They are still valid objects for
which at least the destructor will be called. However, they should also be valid in the sense that they have a
consistent state and all operations work as expected. The only thing you do not know is their value. It is like
using a parameter of the type where you have no clue which value was passed.

2.3.1 Valid but Unspecified State


The C++ standard library guarantees that moved-from objects are in a valid but unspecified state.
Consider the following code:
std::string s;
...
coll.push_back(std::move(s));
After passing s with std::move() you can ask for the number of characters, print out the value, or even
assign a new value. However, you cannot print the first character or any other character without checking
the number of characters first:
foo(std::move(s)); // keeps s in a valid but unclear state

std::cout << s << '\n'; // OK (don’t know which value is written)


std::cout << s.size() << '\n'; // OK (writes current number of characters)
std::cout << s[0] << '\n'; // ERROR (potentially undefined behavior)
std::cout << s.front() << '\n'; // ERROR (potentially undefined behavior)
s = "new value"; // OK
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 29

2.3 Moved-From Objects 29

Although you do not know the value, the string is in a consistent state. For example, s.size() will return
the number of characters so that you can iterate over all valid indexes:
foo(std::move(s)); // keeps s in a valid but unclear state

for (int i = 0; i < s.size(); ++i) {


std::cout << s[i]; // OK
}
For user-defined types you should also ensure that moved-from objects are in a valid state, which sometimes
requires the declaration or implementation of move operations. The chapter Moved-From States will discuss
this in detail.

2.3.2 Reusing Moved-From Objects


You might wonder why moved-from objects are still valid objects and are not (partially) destroyed. The
reason is that there are useful applications of move semantics where it makes sense to use moved-from
objects again.
For example, consider code where we read line-by-line strings from a stream and move them into a
vector:
std::vector<std::string> allRows;
std::string row;
while (std::getline(myStream, row)) { // read next line into row
allRows.push_back(std::move(row)); // and move it to somewhere
}
Each time after we read a line into row, we use std::move() to move the value of row into the vector of
all rows. Then, std::getline() uses the moved-from object row again to read the next line into it.
As a second example, consider a generic function that swaps two values:
template<typename T>
void swap(T& a, T& b)
{
T tmp{std::move(a)};
a = std::move(b); // assign new value to moved-from a
b = std::move(tmp); // assign new value to moved-from b
}
Here, we move the value of a into a temporary object to be able to move-assign the value of b afterwards.
The moved-from object b then receives the value of tmp, which is the former value of a.
Code like this is used in sorting algorithms for example, where we move the values of the different
elements around to bring them into a sorted order. Assigning new values to moved-from objects happens
there all the time. The algorithm might even use the sorting criterion for such a moved-from object.
In general, moved-from objects should be valid objects that can be destroyed (the destructor should not
fail), reused to get other values, and support all other operations objects their type supports without knowing
the value. The chapter Moved-From States will discuss this in detail.
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 30

30 Chapter 2: Core Features of Move Semantics

2.3.3 Move Assignments of Objects to Themselves


The rule that moved-from objects are in a valid but unspecified state usually also applies to objects after a
direct or indirect self-move.
For example, after the following statement, object x is usually valid without its value being known:
x = std::move(x); // afterwards x is valid but has an unclear value
Again, the C++ standard library guarantees that for its objects.1 User-defined types should usually also
provide this guarantee, but sometimes you have to implement something to fix the default-generated moved-
from states.

2.4 Overloading by Different References


After introducing rvalue references, we now have three major ways of call-by-reference:
• void foo(const std::string& arg)
takes the argument as const lvalue reference.
This means that you have only read access to the passed argument. Note that you can pass everything
to a function declared that way if the type fits:
– A modifiable named object
– A const named object
– A temporary object that does not have a name
– An object marked with std::move()
The semantic meaning is that we give foo() read access to the passed argument. The parameter is what
we call an in parameter.
• void foo(std::string& arg)
takes the argument as non-const lvalue reference.
This means that you have write access to the passed argument. Note that you can no longer pass
everything to a function declared that way even if the type fits. You can only pass:
– A modifiable named object
For all other arguments, the call does not compile.
The semantic meaning is that we give foo() read/write access to the passed argument. The parameter
is what we call an out or in/out parameter.
• void foo(std::string&& arg)
takes the argument as non-const rvalue reference.
This also means that you have write access to the passed argument. However, again you have restric-
tions on what you can pass. You can only pass:
– A temporary object that does not have a name
– An non-const object marked with std::move()

1 The guarantees for moved-from library objects were clarified with the library working group issue 2839 (see http:
//wg21.link/lwg2839).
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 31

2.5 Passing by Value 31

The semantic meaning is that we give foo() write access to the passed argument to steal the value. It is
an in parameter with the additional constraint that the caller no longer needs the value.
Note that rvalue references bind to other arguments than non-const lvalue references. Therefore, we had
to introduce a new syntax and could not just implement move semantics as a different way of functions that
modify passed arguments.

2.4.1 const Rvalue References


Technically, there is a fourth way of call-by-reference:
• void foo(const std::string&& arg)
takes the argument as const rvalue reference.
This also means that you have read access to the passed argument. Here, the restrictions would be that
you can only pass:
– A temporary object that does not have a name
– A const or non-const object marked with std::move()
However, there is no useful semantic meaning of this case. As an rvalue reference, stealing the value is
allowed, but being const, we disable any modification of the passed argument. This is a contradiction in
itself.
Nevertheless, creating objects with this behavior is quite easy: Simply mark a const object with
std::move():
const std::string s{"data"};
...
foo(std::move(s)); // would call a function declared as const rvalue reference
This might happen indirectly when declaring a function to return a value with const:
const std::string getValue();
...
foo(getValue()); // would call a function declared as const rvalue reference
Semantically, this case is usually covered by the const lvalue reference overload of a function for read
access. A specific implementation of this case is possible but usually makes no sense (the C++ standard
library class std::optional<> uses const rvalue references).

2.5 Passing by Value


If you declare a function to take an argument by value, move semantics might also (automatically) be used.
For example:
void foo(std::string str); // takes the object by value
...
std::string s{"hello"};
...
foo(s); // calls foo(), str becomes a copy of s
foo(std::move(s)); // calls foo(), s is moved to str
Josuttis: C++ Move Semantics 2022/04/19 13:28 page 32

32 Chapter 2: Core Features of Move Semantics

foo(returnStringByValue()); // calls foo(), return value is moved to str


If the caller signals that it no longer needs the value of the passed argument (by using std::move() or
passing a temporary object without a name), the parameter str is initialized with the value moved from the
passed argument.
That means that with move semantics, call-by-value can suddenly become cheap if a temporary object is
passed or the passed argument is marked with std::move(). Note that just like returning a local object by
value, this move can be optimized away. However, if it is not optimized away, the call is guaranteed to be
cheap now (if move semantics is cheap).
Note the following difference:
void fooByVal(std::string str); // takes the object by value
void fooByRRef(std::string&& str); // takes the object by rvalue reference
...
std::string s1{"hello"}, s2{"hello"};
...
fooByVal(std::move(s1)); // s1 is moved
fooByRRef(std::move(s2)); // s2 might be moved
Here, we compare two functions: one taking the string by value and one taking the string as an rvalue
reference. In both cases we pass a string with std::move().
• The function taking the string by value will use move semantics because a new string is created with the
value of the passed argument.
• The function taking the string by rvalue reference might use move semantics. Passing the argument does
not create a new string. Whether the value of the passed argument is stolen/modified depends on the
implementation of the function.
Thus:
• A function declared to support move semantics might not use move semantics.
• A function declared to take an argument by value will use move semantics.
Note again that the effect of move semantics does not guarantee that any optimization happens at all or
what the effect of any optimization is. All we know is that the passed object is subsequently in a valid but
unspecified state.

2.6 Summary
• Rvalue references are declared with && and no const.
• They can be initialized by temporary objects that do not have a name or non-const objects marked with
std::move().
• Rvalue references extend the lifetime of objects returned by value.
• std::move() is a static_cast to the corresponding rvalue reference type. This allows us to pass a
named object to an rvalue reference.
• Objects marked with std::move() can also be passed to functions taking the argument by const lvalue
reference but not taking a non-const lvalue reference.
Random documents with unrelated
content Scribd suggests to you:
mysterious, and holy, but also rich. For it was to the contented ease
of his early days that he was looking for release; the little haven in
Bedford Park had not come into his dreams. Indeed, I don’t suppose
he had even heard of Bedford Park at that time. It was Islington or
The Manor House; anything in between was Islington. But, of
course, he never confessed to himself that she would need to be
rich.
And he found her. He came over the hills on a gentle April morning
and saw her beneath him. She was caught, it seemed, in a hedge.
How gallantly George bore down to the rescue!
“Can I be of any assistance?” he said in his best manner, and that, I
think, is always the pleasantest way to begin. Between “Can I be of
any assistance?” and “With all my worldly goods I thee endow” one
has not far to travel.
“I’m caught,” she said. “If you could——” Observe George spiking
himself fearlessly.
“I say, you really are! Wait a moment.”
“It’s very kind of you.”
There—he has done it.
“Thank you so much,” she said, with a pretty smile. “Oh, you’ve hurt
yourself!”
The sweet look of pain on her face!
“It’s nothing,” said George nobly. And it really was nothing. One can
get a delightful amount of blood and sympathy from the most
insignificant scratch.
They hesitated a moment. She looked on the ground; he looked at
her. Then his eyes wandered round the beautiful day, and came back
to her just as she looked up.
“It is a wonderful day, isn’t it?” he said suddenly.
“Yes,” she breathed.
It seemed absurd to separate on such a day when they were both
wandering, and Heaven had brought them together.
“I say, dash it,” said George suddenly: “what are you going to do?
Are you going anywhere particular?”
“Not very particular.”
“Neither am I. Can’t we go there together?”
“I was just going to have lunch.”
“So was I. Well, there you are. It would be silly if you sat here and
ate—what are yours, by the way?”
“Only mutton, I’m afraid.”
“Ah, mine are beef. Well, if you sat here and ate mutton sandwiches
and I sat a hundred yards farther on and ate beef ones, we should
look ridiculous, shouldn’t we?”
“It would be rather silly,” she smiled.
So they sat down and had their sandwiches together.
“My name is Carfax,” he said, “Geoffrey Carfax.” Oh, George! And to
a woman! However, she wouldn’t tell him hers.
They spent an hour over lunch. They wandered together for another
hour. Need I tell you all the things they said? But they didn’t talk of
London.
“Oh, I must be going,” she said suddenly. “I didn’t know it was so
late. No, I know my way. Don’t come with me. Good-bye.”
“It can’t be good-bye,” said George in dismay. “I’ve only just found
you. Where do you live? Who are you?”
“Don’t let’s spoil it,” she smiled. “It’s been a wonderful day—a
wonderful little piece of a day. We’ll always remember it. I don’t
think it’s meant to go on; it stops just here.”
“I must see you again,” said George firmly. “Will you be there to-
morrow, at the same time—at the place where we met?”
“I might.” She sighed. “And I mightn’t.”
But George knew she would.
“Then good-bye,” he said, holding out his hand.
“My name is Rosamund,” she whispered, and fled.
He watched her out of sight, marvelling how bravely she walked.
Then he started for home, his head full of strange fancies....
He found a road an hour later; the road went on and on, it turned
and branched and doubled—he scarcely noticed it. The church clock
was striking seven as he came into the village.
It was a wonderful lunch he took with him next day. Chicken and
tongue and cake and chocolate and hard-boiled eggs. He ate it alone
(by the corner of a wood, five miles from the hedge which captured
her) at half-past three. That day was a nightmare. He never found
the place again, though he tried all through the week remaining to
him. He had no hopes after that day of seeing her, but only to have
found the hedge would have been some satisfaction. At least he
could sit there and sigh—and curse himself for a fool.
He went back to Islington knowing that he had had his chance and
missed it. By next April he had forgotten her. He was convinced that
she was not the woman. The woman had still to be found. He went
to another part of the country and looked for her.
And now he was back at “The Dog and Duck” again. Surely he would
find her to-day. It was the time; it must be almost the place. Would
the loved one be there? He was not sure whether he wanted her to
be the woman of five years ago or not. Whoever she was, she would
be the one he sought. He had walked some miles; funny if he
stumbled upon the very place suddenly.
Memories of five years ago were flooding his mind. Had he really
been here, or had he only dreamed of it? Surely that was the hill
down which he had come; surely that clump of trees on the right
had been there before. And—could that be the very hedge?
It was.
And there was a woman caught in it.
IV
George ran down the hill, his heart thumping heavily at his ribs....
She had her back towards him.
“Can I be of any assistance?” he said in his best manner. But she
didn’t need to be rich now; there was that little house at Bedford
Park.
She turned round.
It was Gertie Morrison!
Silly of him; of course, it wasn’t Miss Morrison; but it was
extraordinarily like her. Prettier, though.
“Why, Mr. Crosby!” she said.
It was Gertie Morrison.
“You!” he said angrily.
He was furious that such a trick should have been played upon him
at this moment; furious to be reminded suddenly that he was
George Crosby of Muswell Hill. Muswell Hill, the boarding-house—
Good Lord! Gertie Morrison! Algy Traill’s Gertie.
“Yes, it’s me,” she said, shrinking from him. She saw he was angry
with her; she vaguely understood why.
Then George laughed. After all, she hadn’t deliberately put herself in
his way. She could hardly be expected to avoid the whole of England
(outside Muswell Hill) until she knew exactly where George Crosby
proposed to take his walk. What a child he was to be angry with her.
When he laughed, she laughed too—a little nervously.
“Let me help,” he said. He scratched his fingers fearlessly on her
behalf. What should he do afterwards? he wondered. His day was
spoilt anyhow. He could hardly leave her.
“Oh, you’ve hurt yourself!” she said. She said it very sweetly, in a
voice that only faintly reminded him of the Gertie of Muswell Hill.
“It’s nothing,” he answered, as he had answered five years ago.
They stood looking at each other. George was puzzled.
“You are Miss Morrison, aren’t you?” he said. “Somehow you seem
different.”
“You’re different from the Mr. Crosby I know.”
“Am I? How?”
“It’s dreadful to see you at the boarding-house.” She looked at him
timidly. “You don’t mind my mentioning the boarding-house, do
you?”
“Mind? Why should I?” (After all, he still had another week.)
“Well, you want to forget about it when you’re on your holiday.”
Fancy her knowing that.
“And are you on your holiday too?”
She gave a long deep sigh of content.
“Yes,” she said.
He looked at her with more interest. There was colour in her face;
her eyes were bright; in her tweed skirt she looked more of a
country girl than he would have expected.
“Let’s sit down,” he said. “I thought you always went to Mar—to
Cliftonville for your holiday?”
“I always go to my aunt’s there in the summer. It isn’t really a
holiday; it’s more to help her; she has a boarding-house too. And it
really is Cliftonville—only, of course, it’s silly of mother to mind
having it called Margate. Cliftonville’s much worse than Margate
really. I hate it.”
(This can’t be Gertie Morrison, thought George. It’s a dream.)
“When did you come here?”
“I’ve been here about ten days. A girl friend of mine lives near here.
She asked me suddenly just after you’d gone—I mean about a
fortnight ago. Mother thought I wasn’t looking well and ought to go.
I’ve been before once or twice. I love it.”
“And do you have to wander about the country by yourself? I mean,
doesn’t your friend—I say, I’m asking you an awful lot of questions.
I’m sorry.”
“That’s all right. But, of course, I love to go about alone, particularly
at this time of year. You understand that.”
Of course he understood it. That was not the amazing thing. The
amazing thing was that she understood it.
He took his sandwiches from his pocket.
“Let’s have lunch,” he said. “I’m afraid mine are only beef.”
“Mine are worse,” she smiled. “They’re only mutton.”
A sudden longing to tell her of his great adventure of five years ago
came to George. (If you had suggested it to him in March!)
“It’s rather funny,” he said, as he untied his sandwiches—“I was
down here five years ago——”
“I know,” she said quietly.
George sat up suddenly and stared at her.
“It was you!” he cried.
“Yes.”
“You. Good Lord!... But your name—you said your name was—wait a
moment—that’s it! Rosamund!”
“It is. Gertrude Rosamund. I call myself Rosamund in the country. I
like to pretend I’m not the”—she twisted a piece of grass in her
hands, and looked away from him over the hill—“the horrible girl of
the boarding-house.”
George got on to his knees and leant excitedly over her.
“Tell me, do you hate and loathe and detest Traill and the Fossetts
and Ransom as much as I do?”
She hesitated.
“Mr. Ransom has a mother in Folkestone he’s very good to. He’s not
really bad, you know.”
“Sorry. Wash out Ransom. Traill and the Fossetts?”
“Yes. Oh yes. Oh yes, yes, yes.” Her cheeks flamed as she cried it,
and she clenched her hands.
George was on his knees already, and he had no hat to take off, but
he was very humble.
“Will you forgive me?” he said. “I think I’ve misjudged you. I mean,”
he stammered—“I mean, I don’t mean—of course, it’s none of my
business to judge you—I’m speaking like a prig, I—oh, you know
what I mean. I’ve been a brute to you. Will you forgive me?”
She held out her hand, and he shook it. This had struck him, when
he had seen it on the stage, as an absurdly dramatic way of making
friends, but it seemed quite natural now.
“Let’s have lunch,” she said.
They began to eat in great content.
“Same old sandwiches,” smiled George. “I say, I suppose I needn’t
explain why I called myself Geoffrey Carfax.” He blushed a little as
he said the name. “I mean, you seem to understand.”
She nodded. “You wanted to get away from George Crosby; I know.”
And then he had a sudden horrible recollection.
“I say, you must have thought me a beast. I brought a terrific lunch
out with me the next day, and then I went and lost the place. Did
you wait for me?”
Gertie would have pretended she hadn’t turned up herself, but
Rosamund said, “Yes, I waited for you. I thought perhaps you had
lost the place.”
“I say,” said George, “what lots I’ve got to say to you. When did you
recognise me again? Fancy my not knowing you.”
“It was three years, and you’d shaved your moustache.”
“So I had. But I could recognise people just as easily without it.”
She laughed happily. It was the first joke she had heard him make
since that day five years ago.
“Besides, we’re both different in the country. I knew you as soon as
I heard your voice just now. Never at all at Muswell Hill.”
“By Jove!” said George, “just fancy.” He grinned at her happily.
After lunch they wandered. It was a golden afternoon, the very
afternoon they had had five years ago. Once when she was crossing
a little stream in front of him, and her foot slipped on a stone, he
called out, “Take care, Rosamund,” and thrilled at the words. She let
them pass unnoticed; but later on, when they crossed the stream
again lower down, he took her hand and she said, “Thank you,
Geoffrey.”
They came to an inn for tea. How pretty she looked pouring out the
tea for him—not for him, for them; the two of them. She and he! His
thoughts became absurd....
Towards the end of the meal something happened. She didn’t know
what it was, but it was this. He wanted more jam; she said he’d had
enough. Well, then, he wasn’t to have much, and she would help
him herself.
He was delighted with her.
She helped him ... and something in that action brought back swiftly
and horribly the Gertie Morrison of Muswell Hill, the Gertie who sat
next to Algy and helped him to cabbage. He finished his meal in
silence.
She was miserable, not knowing what had happened.
He paid the bill and they went outside. In the open air she was
Rosamund again, but Rosamund with a difference. He couldn’t bear
things like this. As soon as they were well away from the inn he
stopped. They leant against a gate and looked down into the valley
at the golden sun.
“Tell me,” he said, “I want to know everything. Why are you—what
you are, in London?”
And she told him. Her mother had not always kept a boarding-
house. While her father was alive they were fairly well off; she lived
a happy life in the country as a young girl. Then they came to
London. She hated it, but it was necessary for her father’s business.
Then her father died, and left nothing.
“So did my father,” said George under his breath.
She touched his hand in sympathy.
“I was afraid that was it.... Well, mother tried keeping a boarding-
house. She couldn’t do it by herself. I had to help. That was just
before I met you here.... Oh, if you could know how I hated it. The
horrible people. It started with two boarders. Then there was one—
because I smacked the other one’s face. Mother said that wouldn’t
do. Well, of course, it wouldn’t. I tried taking no notice of them.
Well, that wouldn’t do either. I had to put up with it; that was my
life.... I used to pretend I was on the stage and playing the part of a
landlady’s vulgar daughter. You know what I mean; you often see it
on the stage. That made it easier—it was really rather fun
sometimes. I suppose I overplayed the part—made it more common
than it need have been—it’s easy to do that. By-and-by it began to
come natural; perhaps I am like that really. We weren’t anybody
particular even when father was alive. Then you came—I saw you
were different from the rest. I knew you despised me—quite right
too. But you really seemed to hate me, I never quite knew why. I
hadn’t done you any harm. It made me hate you too.... It made me
want to be specially vulgar and common when you were there, just
to show you I didn’t mind what you thought about me.... You were
so superior.
“I got away in the country sometimes. I just loved that. I think I was
really living for it all the time.... I always called myself Rosamund in
the country.... I hate men—why are they such beasts to us always?”
“They are beasts,” said George, giving his sex away cheerfully. But
he was not thinking of Traill and the Fossetts; he was thinking of
himself. “It’s very strange,” he went on; “all the time I thought that
the others were just what they seemed to be, and that I alone had a
private life of my own which I hid from everybody. And all the time
you.... Perhaps Traill is really somebody else sometimes. Even
Ransom has his secret—his mother.... What a horrible prig I’ve
been!”
“No, no! Oh, but you were!”
“And a coward. I never even tried.... I might have made things much
easier for you.”
“You’re not a coward.”
“Yes, I am. I’ve just funked life. It’s too much for me, I’ve said, and
I’ve crept into my shell and let it pass over my head.... And I’m still a
coward. I can’t face it by myself. Rosamund, will you marry me and
help me to be braver?”
“No, no, no,” she cried, and pushed him away and laid her head on
her arms and wept.
Saved, George, saved! Now’s your chance. You’ve been rash and
impetuous, but she has refused you, and you can withdraw like a
gentleman. Just say “I beg your pardon,” and move to Finsbury Park
next month ... and go on dreaming about the woman. Not a
landlady’s vulgar little daughter, but——
George, George, what are you doing?
He has taken the girl in his arms! He is kissing her eyes and her
mouth and her wet cheeks! He is telling her....
I wash my hands of him.
V
John Lobey, landlord of “The Dog and Duck,” is on the track of a
mystery. Something to do with they anarchists and such-like. The
chief clue lies in the extraordinary fact that on three Sundays in
succession Parson has called “George Crosby, bachelor, of this
parish,” when everybody knows that there isn’t a Crosby in the
parish, and that the gentleman from London, who stayed at his inn
for three weeks and comes down Saturdays—for which purpose he
leaves his bag and keeps on his room—this gentleman from London,
I tell you, is Mr. Geoffrey Carfax. Leastways it was the name he
gave.
John Lobey need not puzzle his head over it. Geoffrey Carfax is
George Crosby, and he is to be married next Saturday at a
neighbouring village church, in which “Gertrude Rosamund Morrison,
spinster, of this parish,” has also been called three times. Mr. and
Mrs. Crosby will then go up to London and break the news to Mrs.
Morrison.
“Not until you are my wife,” said George firmly, “do you go into that
boarding-house again.” He was afraid to see her there.
“You dear,” said Rosamund; and she wrote to her mother that the
weather was so beautiful, and she was getting so much stronger,
and her friend so much wanted her to stay, that ... and so on. It is
easy to think of things like that when you are in love.
On the Sunday before the wedding George told her that he had
practically arranged about the little house in Bedford Park.
“And I’m getting on at the office rippingly. It’s really quite interesting
after all. I shall get another rise in no time.”
“You dear,” said Rosamund again. She pressed his hand tight and....
But really, you know, I think we might leave them now. They have
both much to learn; they have many quarrels to go through, many
bitter misunderstandings to break down; but they are alive at last.
And so we may say good-bye.
The Cherub
By Oliver Onions

Army Service Corps

It was provided in the roster of Garrison Duties, Section “Guards and


Picquets,” that a sentry should march and return along that portion
of the grey wall that lay between the Sowgate Steps and the Tower
of the ancient South Bar, a hundred yards away; but fate alone had
determined that that sentry should be Private Hey. And, since Private
Hey was barely tall enough to look forth from the grey embrasures
of the outer wall to the pleasant Maychester Plain where the placid
river wound, the same fate had further decreed that his gaze should
be directed inwards, over the tall trees below him, to the row of
Georgian houses of mellow plum-like brick that stood beyond the
narrow back gardens, and past these again to other trees and other
houses, to where the minster towers arose in the heart of the
ancient city. Only occasionally did a fleeting, pathetic wonder cross
Private Key’s mind whether there was an irony in this.
A lithograph of uniforms outside the post office (guards, artillery,
and militia, all in one frame) had turned his thoughts to the Army
seven years before, and the recruiting-sergeant had clinched the
matter. Until then he had been a builder’s clerk. He was just five-
and-twenty. He had a pink, round face, wide-open blue eyes, the
slightest of blond moustaches, and his soft, slack mouth seemed
only to be held closed by his chin-strap. He always looked hot and
on the point of perspiration.
Knowing something of the building trade, it had been his
amusement, while on his lofty beat, to work out in his mind the
interiors of the Georgian houses of which he saw only the outsides.
With the chimney-stacks thus and thus, the fireplaces were probably
distributed after such and such a fashion; white-sashed windows
irregularly placed among the ivy doubtless gave on landings; waste
and cistern-pipes were traceable to sources here and there; and
Private Hey had his opinion on each of the chimney-cowls that
turned this way and that with the wind. He knew the habits, too, of
the folk on whose back gardens he looked down. The nurse in native
robes reminded him of his five years in India; the old lady in black
merino who fed the birds was familiar; and he liked to see the
children who spread white cloths on the grass beneath the pear and
cherry trees and held their small tea-parties. Sometimes he
wondered whether, to them, so far above them, he did not look like
one of the scarlet geraniums of their own window-boxes.
It had been during the previous spring that the incoming of a new
tenant to the end house of the row had interested him mildly. He
had watched the white-jacketed house-painters at work, and had
reflected that the small window they were covering with a coloured
transparency was probably that of a bathroom. Then the new
tenants had moved in, and one day a small, plump woman’s figure
had appeared shaking a table-cloth at the top of the narrow garden.
The sentry had stopped suddenly in his beat, and broken into the
sweat he always seemed on the point of. Even at that distance he
had recognised her; and when, after some minutes, he had begun to
think again, the only idea that had come to him was, why, during the
seven years in which he had not ceased to think of Mollie Westwood,
had he never once pictured her in a blue gown?
But she was Mollie Hullah now; he knew that. And he knew Hullah,
too, architect and surveyor. Hullah had been the foreman of
Peterson’s building yard in the days when he, Tom Hey, civilian, had
been Peterson’s junior clerk. He remembered him as an ambitious
sort of chap, who (while Tom Hey had “flown his kite,” as he put it)
had bought himself a case of instruments and a reel-tape, and
studied, and made himself an architect. Tom Hey’s duties had been
confined to the day-book; Hullah and Peterson between them
contained the true account of the Peterson business; and Hey had
not guessed the reason for this until, in India, he had received the
newspaper that contained the account of Peterson’s bankruptcy.
Then he had “tumbled.” The examination showed Peterson’s books
to have been ill-kept with a sagacity and foresight that had drawn
forth ironical compliments from the registrar himself. “Your chief
witness abroad, too; excellent!” the registrar had commented.... No;
Hullah was not the fellow to tell all he knew about contractors and
palm-oil and peculating clerks-of-works. Hullah was the kind of man
who got on.
Since Hullah had come to live in the end house, Private Hey, eyes-
right when he turned at the South Bar, and eyes-left when he turned
again at the Sowgate Steps, had counted the days when Mollie had
appeared at the windows or shaken the table-cloth in the narrow
garden. His amusement was no longer with chimney-pots and bath-
rooms; it was, to tell over to himself the dissolute life he had led
since Mollie had turned her back on him. Somehow, it seemed to
exalt her.
It was not that he had ever lied, or stolen, or left a friend in trouble.
To the pink-faced private these things were not merely wicked; they
were “dead off”—a much worse thing. He drew the line at things
that were “off.” But he had committed a monotonous routine of
other sins, beginning usually at the canteen, continuing at the
“regulation” inns or at the Cobourg Music-hall, and ending on the
defaulter-sheet with a C.B. And one day his colonel had said to him:
“Hey, you remind me of a cherub who kicks about in the mud and
glories to think himself an imp.” That had puzzled and troubled Hey,
for he liked the fine old colonel.
“He forgot everything except little Mollie Westwood” (page 35).
For he had ranked himself with the magnificently wicked. In amours,
short of anything that was “off,” was he not a Juan? In the matter of
inebriety, and for brawling in the streets, why, his officers might
make war with ceremony and all that, but (the cherub flattered
himself) he was an item of the reckless, heroic, glorious stuff they
had to do it with. And since Mollie, by refusing him, had driven him
to all this, the sight of her ought surely to have inspired him in his
courses; it troubled him that it did not do so. On the contrary, he
never felt less inclination to fuddle himself or to click his heels over
the gallery-rail of the Cobourg than when he had seen her. When he
did not see her, these things were less difficult, and that again was
wrong. To regulate his conduct at all by the sight of another man’s
wife was, of all dead-off things, the deadest.
Now Hullah, as the sentry knew, had no family; but when, the
following spring, the apple trees put forth their pink, and the white
clouds sailed high over Maychester, and the note of the cuckoo
floated on the air, the cherub became moody and bashful and
changed colour ten times in an hour. Thrushes and blackbirds flew
back and forth from their nests; and Mollie, too, her figure dwarfed
by his point of vantage, sunned herself in the garden. Sometimes
the cherub blushed red as his tunic. He ought to have gone to the
Cobourg and played the very deuce; instead, off duty, he wandered
unhappily alone. Then one day he missed her, and his eyes scanned
the house and her windows timorously.
Six weeks passed. Then one morning he saw that the white blinds
were drawn. His face became white as wax.
The next day he saw the tail of a coach beyond the end of the
house. He exceeded his beat, descended the Sowgate Steps, and
stood, trembling and watching. Then he gave a great sob of relief.
The coach had turned; the horse wore white conical peaks of linen
on its ears—the mark of a child’s funeral. The small procession
passed, and the cherub resumed his beat.
That evening the colonel stopped him as he crossed the barrack
yard.
“Ah, Hey!... I’m glad you’ve given us so little trouble lately. I’d try to
keep it up if I were you.”
“Yes, sir,” said the cherub, saluting; and the colonel nodded kindly
and passed on.

The July sun beat fiercely down on the grey walls, and the sentry’s
tunic was of a glaring bull’s red. Not a breath moved the trees
below, and the click of his heels sounded monotonously.
Within the shadow of the South Bar, where the steps wound down to
the street, a frock-coated, square-built man of forty, with clipped
whiskers and crafty eyes, watched the sentry approach. For the
second time he cleared his throat and said “Tom!”
This time the sentry turned. “I ain’t allowed to talk on duty,” he said.
The man within the shadow waited.
He waited for half an hour, and then the clatter of the relief was
heard ascending the turret. Presently Private Hey passed him
without looking at him. He descended after him, and in the street
spoke again.
“I ain’t off duty yet; you can come to the Buttercup,” said Private
Hey.
The bar of the Buttercup was below the level of the street, and a
gas-jet burned all day over its zinc-covered counter. In the back
parlour behind it Hullah awaited Private Hey.
The cherub’s voice was heard shouting an order, and he entered the
snug. The uncoated barman followed him with the liquor, and
retired.
“Did you want to speak to me?” the cherub demanded.
“I did, Tom, I did. How—how are you getting on?”
“Spit it out.”
Hullah murmured smoothly: “Ah, the same blunt-spoken, honest
Tom that was at Peterson’s! You remember Peterson’s and the old
days, Tom?”
“I’d let the old days drop if I was you. I thought you had done.”
“So did I, Tom, so did I; but every breast has its troubles. You’ve
heard the expression, Tom, that there is no cupboard without its
skeleton?”
“Keep your cupboards and skeletons to yourself.... Does the new
bathroom answer all right?”
“Nicely, Tom, I thank you.... Did you know Peterson was back in
Maychester?”
“Ho, is he? I expect he wants to talk over the old days with his
friend Hullah, same as you with me. Well, you was a precious pair o’
rascals—though for myself, mark you, I like to see honour among
such.”
“Hush, Tom!... He’s back, and seeking you. He’d better be careful;
it’s twenty years, is that. But what I wanted to say, Tom, is that it
would save a lot of trouble—a lot of trouble—if you weren’t to see
him.”
“Ho!... Hullah, my man.”
“Yes, Tom.”
“Do you know what I think you are?”
Hullah stammered. It was so hard to get a start in business—the
competition—he’d gone straight except for that once.
“I think you’re the blackguardest, off-est scamp in the trade, and I
wouldn’t be found dead in a ditch with you. That’s juicy, coming
from me. I’m no saint, but just a common-or-garden Tommy, with a
defaulter sheet it’s a sin to read; and I say you’re a blackguard, and
dead-off.”
Hullah cringed. He’d gone straight since—Peterson had already
pushed him for twice what he’d had out of it—it was hard to be
persecuted like this, hard. The cherub revolved in his mind phrases
of elaborate and over-done irony.
Suddenly Hullah mentioned his wife, and the pink of the cherub’s
face deepened.
“Come into the yard,” he said.
Hullah followed him into a dusty plot, where hens scratched and
cases and barrels lay scattered everywhere.
“What did you say?” the soldier demanded.
The architect’s face was of an unwholesome white, and Hey spat. He
saw that Hullah feared he was going to strike him.
“She’s been ill, Tom, and must be got away to the Mediterranean.
Peterson’s sucking me dry; he thinks I’m afraid of him. You used to
be fond of her, Tom.”
All at once Private Hey’s wrath gave place to utter wretchedness,
and he began to stride up and down the yard. Tears rose into his
eyes, and presently rolled unchecked down his cheeks. He
approached Hullah, and said in a quavering voice: “A fortnight ago—
was that?”
“A boy,” Hullah murmured.
“It’s a mercy he’s dead, if he’d ha’ been like you,” the cherub
sobbed.
And then he forgot all about Hullah. He forgot everything except that
little Mollie Westwood had been through an agony, was ill, must be
got away, and that he might help her. An ineffable, soft thrill stirred
at his heart; he, wicked Tom Hey, might help her. And presently he
stood before Hullah again, looking wistfully at him.
“You ain’t lying, Hullah?”
“Oh, Tom!”
“And suppose—suppose I was to think Peterson’s as big a thief as
you, and treat him as such—treat him as such, if he dares to speak
to me; you understand, Hullah?”
“Don’t put it that way, Tom ... then I may take it, Tom——?”
“Oh, go, go! I want to me by myself!” the poor cherub moaned; and
Hullah, turning once to dart a hateful glance at him over his
shoulder, passed through the public-house.

“It’s Siberia for you this time, Tom,” the guard whispered, adjusting
his pipe-clayed belt; “what in thunder made you go and do it?”
The cherub’s tunic was unbelted, and the colour had fled from his
simple face. He made no reply.
“Was you drunk? Barker says you hadn’t been in the canteen.
Anyway, the chap’s in ’orspital. A blooming civilian, too!”
He saluted stiffly; the major had passed on his way to the
outbuilding that had been furnished for a court-martial; and the
barrack clock struck eleven.
Half a dozen officers in full uniform sat about a long trestle-table,
and the sunlight that came through the tall windows lay across the
pens and ink and pink blotting-paper that were spread before the
Court. The colonel, at the head of the table, talked to Warren, the
regimental surgeon.
“I’m absurdly upset, Warren. It’s ridiculous, the faith I have in the
fellow. Moreover, I have reason to know that he hasn’t touched drink
for weeks.”
“He’s been in the habit, and in such cases a sudden discontinuance
sometimes.... But the point isn’t whether he was drunk or not; it’s an
unprovoked attack on this fellow Peterson, or whatever his name is.”
The colonel sighed. “Ah, well, I can’t overlook this. Are you ready,
gentlemen?”
An orderly opened the door, and the prisoner was brought in
between two armed guards. He saluted the Court, and then stood at
attention. The guards fell back. Two or three witnesses sat on a
bench within the door.
The colonel did not once look at Private Hey, and the charge was
read. The principal witness lay in hospital, but sufficient evidence of
the fact of the assault would be produced, and the president desired
the prisoner to plead. The plea was scarcely audible, but it was
understood to be “Not guilty,” and the first witness was called.
The cherub knew not in what queer way it hurt him that his colonel
refused to look at him. He didn’t much care what happened, but he
would have liked the colonel to think well of him. A witness was
telling how the prisoner had reeled, spoken thickly, offered his
bayonet, and finally flung the man down the steps of the turret of
the South Bar. Would the witness consider the prisoner to have been
drunk? the Court asked, and the witness replied that he should. The
steps were old and worn; might not the man have slipped? the Court
suggested, and the witness reminded the Court that the prisoner
had staggered and offered his bayonet. Had the injured man spoken
to the prisoner? The witness thought not; he had seemed to be on
the point of speaking, but the prisoner had cut him short,
exclaiming: “I don’t want to talk to dead-off’s—like you!”
Asked if he had anything to say, the prisoner shook his head. “I
wasn’t drunk, sir,” he said.
Other witnesses were called; the case went drowsily forward, and
the major yawned. The colonel was whispering to the doctor again,
and then for the first time he looked at the prisoner.
“Do you know this Peterson?”
“I worked for him when I was a civilian, sir,” the prisoner answered.
“Have you any grudge against him?”
“I didn’t want to talk to him, sir.”
“But suppose he should speak to you again?”
A brief gleam of satisfaction crossed the cherub’s mild blue eyes. “I
frightened him too bad for that, sir,” he said; and then, as the
colonel’s grave eyes did not cease to regard him, there came a quick
little break in his voice.
“I wasn’t drunk, sir. I wouldn’t tell you a lie, sir, nor do nothing that’s
off—there’s marks against me a many, but not for things that’s off; I
ask you to believe I wasn’t drunk, sir——”
“Clear the Court,” said the colonel.
The guard, the prisoner, and the witnesses filed out and the door
closed, and the colonel leaned forward in his chair. He seemed
disproportionately moved.
“Gentlemen,” he said, “if the prisoner is to be seriously punished, I
ask you to remember it’s dismissal and imprisonment. Let me make
a suggestion. It was a very hot day—he’s been in India—possibly an
old sunstroke——”
“A bit discredited, that,” observed the doctor.
“He would be punished, of course, but more leniently. It’s all I can
put forward. It rests with the Court.”
He leaned back again, troubled. In the hum of consultation he heard
Warren’s slightly sarcastic laugh, and thought he heard the major
say: “Oh, let it go at that; Neville seems to want it.”
“Very well, sir,” said the major by and by; “we are agreed.”
And as the cherub, returning with the guard, received the milder
sentence, he looked humbly and gratefully at his colonel. He
recognised that there are things that a commanding officer cannot
overlook, but that a private gentleman, on occasion, may.
An Impossible Person
By W. B. Maxwell

Royal Fusiliers

Using the cant phrase, people often said that General Sir John
Beckford was a quite impossible person. A brave soldier, a true
gentleman, a splendid creature physically—just so, but rendering
himself absurd and futile by notions so old-fashioned that they had
been universally exploded before he was born. A man who
obstinately refused to move with the times, who in manner,
costume, and every idea belonged, and seemed proud to belong, to
the past.
Even his own relatives admitted the impossibility of him when, at the
age of sixty, he gave effect to the most old-fashioned of all
conceivable notions by marrying for love. If an elderly widower with
a little son of nine wants somebody to make a home and help to
rear the child, he should invite some middle-aged female cousin to
come to his assistance; but if he wants a charming, attractive girl to
renounce the joys and hopes of youth in order to soothe and
gladden his dull remnant of years—well, he oughtn’t to want it, and
really it is not quite nice when he does.
Lady Jane Armitage, an ancient aunt, put this thought into very plain
words and forced Sir John to listen to them. A mistake—not even a
fair bargain. What is Cynthia to get, on her side? A seat in a
carriage, a liberal dress allowance, perhaps a few more loose
sovereigns than she has been accustomed to carry in that silly little
gold purse of hers!
“The idea of money,” said Sir John gruffly, “has never entered
Cynthia’s head.”
“Perhaps not. But what else can you offer her? To hold your landing-
net while you do your stupid fishing; to perform the duties of a
nursery-governess for Jack; to enjoy the privilege of playing hostess
when you entertain half a dozen other generals and their frumpish
wives.”
Sir John echoed his aunt’s last adjective ironically.
“Yes,” said Lady Jane, “but I’m different. I know I’m a frump, and
your friends aren’t aware of their misfortune. No, John, I tell you
frankly, it isn’t a fair bargain.”
Sir John bit his grey moustache, ran a strong hand through his shock
of grey hair, contracted his heavy brows, and then laughed and
shrugged his shoulders.
“Inexplicable to you, eh, Aunt Jane? Well, let’s leave it at that. But
be kind to Cynthia all the same, won’t you? Save her from the other
frumps,” and, ceasing to laugh, he stared at Lady Jane almost
fiercely.
He was one of those men who consider it beneath their dignity to
betray tender emotion, and who perhaps look sternest and most
forbidding when they are feeling unusually soft and gentle. At any
rate, he would not explain to his aunt that he believed the marriage
to be an eminently fair bargain—an old-fashioned exchange—love
for love—as much love on the girl’s side as on his.
Lady Jane made no promise, but she proved very kind indeed to her
new niece; endeavouring to find innocent amusement for pretty
Cynthia, acting as her chaperon, watching over her, and growing
fonder and fonder of her. She said that the young Lady Beckford was
a model wife and a pattern stepmother. No one could have been
more devoted to or wiser in her training of Master Jack.
Now, after five years, the boy was ready to go to a public school,
and during these long summer days a holiday tutor had been giving
him final preparation, ultimate crammed knowledge, and topmost
polish of tone and manners. August had been spent at the
Beckfords’ country house in Devonshire, and the early weeks of
September at their flat in Victoria Street. Lady Jane approved of
everything that concerned these arrangements, except one thing.
She approved of the public school, of the engaging of a holiday
tutor, of all the care, devotion, and forethought with which the little
man was being launched from the home circle; but she did not
approve of the fact that Sir John had thrown the whole burden on
Cynthia’s slender shoulders, while he did his stupid salmon-fishing
four hundred miles away in Scotland.
Not quite fair to Cynthia—leaving her all alone with a schoolboy and
his tutor. Lady Jane, at considerable inconvenience, ran down to
Devonshire to cheer and enliven her. Came back to London and at
worse inconvenience stayed there, so as to be handy to act as
companion, chaperon, advisory ally, whenever Cynthia wanted her.
But Cynthia wanted her scarcely at all, and allowed poor Lady Jane
to perceive at last that uninvited companions are sometimes a
tedium rather than a solace.

It was the last night of the holidays. To-morrow Master Jack and his
tutor would disappear from Victoria Street.
Dinner had been ordered at an early hour, and Jack was scampering
through his meal with excited swiftness. One last treat had been
arranged for him. He was to be dispatched to a theatre presently in
charge of George, the footman.
“I wish you were coming,” said Jack, and as he turned to Mr.
Ridsdale his eyes expressed eloquently enough the hero-worship
that is so easy to kindle in young and ingenuous hearts.
“It would be scarcely polite,” said Mr. Ridsdale, “for both of us to
desert Lady Beckford.”
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like