This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Move Constructors and Move Assignment Operators (C++)

  • 9 contributors

This topic describes how to write a move constructor and a move assignment operator for a C++ class. A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: && .

This topic builds upon the following C++ class, MemoryBlock , which manages a memory buffer.

The following procedures describe how to write a move constructor and a move assignment operator for the example C++ class.

To create a move constructor for a C++ class

Define an empty constructor method that takes an rvalue reference to the class type as its parameter, as demonstrated in the following example:

In the move constructor, assign the class data members from the source object to the object that is being constructed:

Assign the data members of the source object to default values. This prevents the destructor from freeing resources (such as memory) multiple times:

To create a move assignment operator for a C++ class

Define an empty assignment operator that takes an rvalue reference to the class type as its parameter and returns a reference to the class type, as demonstrated in the following example:

In the move assignment operator, add a conditional statement that performs no operation if you try to assign the object to itself.

In the conditional statement, free any resources (such as memory) from the object that is being assigned to.

The following example frees the _data member from the object that is being assigned to:

Follow steps 2 and 3 in the first procedure to transfer the data members from the source object to the object that is being constructed:

Return a reference to the current object, as shown in the following example:

Example: Complete move constructor and assignment operator

The following example shows the complete move constructor and move assignment operator for the MemoryBlock class:

Example Use move semantics to improve performance

The following example shows how move semantics can improve the performance of your applications. The example adds two elements to a vector object and then inserts a new element between the two existing elements. The vector class uses move semantics to perform the insertion operation efficiently by moving the elements of the vector instead of copying them.

This example produces the following output:

Before Visual Studio 2010, this example produced the following output:

The version of this example that uses move semantics is more efficient than the version that does not use move semantics because it performs fewer copy, memory allocation, and memory deallocation operations.

Robust Programming

To prevent resource leaks, always free resources (such as memory, file handles, and sockets) in the move assignment operator.

To prevent the unrecoverable destruction of resources, properly handle self-assignment in the move assignment operator.

If you provide both a move constructor and a move assignment operator for your class, you can eliminate redundant code by writing the move constructor to call the move assignment operator. The following example shows a revised version of the move constructor that calls the move assignment operator:

The std::move function converts the lvalue other to an rvalue.

Rvalue Reference Declarator: && std::move

Was this page helpful?

Additional resources

  • Sign In / Suggest an Article

Current ISO C++ status

Upcoming ISO C++ meetings

Upcoming C++ conferences

Compiler conformance status

CppCon 2024

September 15-20, Aurora, CO, USA

Meeting C++ 2024

November 14-16, Berlin, Germany

Friendly reminder to mark your move constructors noexcept -- AndyG

By andyg | Sep 1, 2020 07:15 AM | Tags: None

AndyG warns us that if you're upgrading to Visual Studio 2017, you might be incurring some unexpected performance overhead thanks to better noexcept support.

Friendly reminder to mark your move constructors noexcept by AndyG

From the article:

Since C++11 we have had the noexcept keyword, which is a promise that the function will not throw an exception (and if it does, go straight to std::terminate , do not pass go). noexcept is nice for two reasons: The compiler can optimize a little better because it doesn’t need to emit any code for unwinding a call stack in case of an exception, and It leads to incredible performance differences at runtime for std::vector (and other containers, too)

Share this Article

Add a comment.

You must sign in or register to add a comment.

Comments (0)

There are currently no comments on this entry.

27.10 — std::move_if_noexcept

It gets interesting in the third line. We created moved_pair by copy constructing its CopyClass subobject (it doesn’t have a move constructor), but that copy construction threw an exception since we changed the Boolean flag. Construction of moved_pair was aborted by the exception, and its already-constructed members were destroyed. In this case, the MoveClass member was destroyed, printing destroying MoveClass(13) variable . Next we see the Error found: abort! message printed by main() .

  • C++ Data Types
  • C++ Input/Output
  • C++ Pointers
  • C++ Interview Questions
  • C++ Programs
  • C++ Cheatsheet
  • C++ Projects
  • C++ Exception Handling
  • C++ Memory Management

Move Assignment Operator in C++ 11

In C++ programming, we have a feature called the move assignment operator, which was introduced in C++11. It helps us handle objects more efficiently, especially when it comes to managing resources like memory. In this article, we will discuss move assignment operators, when they are useful and called, and how to create user-defined move assignment operators.

Move Assignment Operator

The move assignment operator was added in C++ 11 to further strengthen the move semantics in C++. It is like a copy assignment operator but instead of copying the data, this moves the ownership of the given data to the destination object without making any additional copies. The source object is left in a valid but unspecified state.

User-Defined Move Assignment Operator

The programmer can define the move assignment operator using the syntax given below:

As you may have noticed, the move assignment operator function uses a special && reference qualifier. It represents the r-value references (generally literals or temporary values).

Usually, it returns a reference to the object (in this case, *this) so you can chain assignments together.

The move constructor is called by the compiler when the argument is an rvalue reference which can be done by std::move() function. 

Example of Move Assignment Operator

In this program, we will create a dynamic array class and create a user-defined move assignment operator.

                               

Explanation

The move assignment operator (operator=) is used to transfer resources from one DynamicArray object to another. It releases the current resources of the destination object, takes the resources from the source object, and leaves the source object in a valid but unspecified state.

In the main function:

  • We create two DynamicArray objects, arr1 with 5 elements and arr2 with 10 elements. We print their initial states.
  • We use the move assignment operator to transfer the resources from arr1 to arr2 by calling arr2 = std::move(arr1).
  • After the move, we print the states of both arr1 and arr2. arr1 is now in a valid but unspecified state, and arr2 contains the resources of arr1.
Note: We can also define a move constructor with a move assignment operator and reduce the code redundancy by calling the move assignment operator from the move constructor. To know about move constructor, refer to the article – Move Constructors in C++

Implicit Definition of Move Assignment Operator

The compiler also defines a default move assignment operator implicitly when the following conditions are satisfied:

  • No user-defined copy constructor is present.
  • No user-defined destructor is present.
  • No user-defined move constructor is present.

Need of Move Assignment Operator

In C++, objects can manage resources like memory. When we copy an object, it can be quite slow, especially if the object holds a lot of resources. Traditional copy operations create new copies, which can lead to unnecessary memory usage and slow down your program.

This is where move assignment operators come to the rescue. They let one object take over the resources of another, without making extra copies. This can significantly boost performance in scenarios like resizing arrays or returning objects from functions.

In contrast to the copy assignment operator, the end result of the move assignment operator will be a single copy of the source object.

Please Login to comment...

Similar reads.

  • Geeks Premier League
  • Geeks Premier League 2023
  • SUMIF in Google Sheets with formula examples
  • How to Get a Free SSL Certificate
  • Best SSL Certificates Provider in India
  • Elon Musk's xAI releases Grok-2 AI assistant
  • Content Improvement League 2024: From Good To A Great Article

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

C++中为什么move construct需要加noexcept

C++ 11中增加了名为 移动构造函数 的构造函数类型。通过使用移动构造函数,我们可以在进行对象复制时直接“窃取”拷贝对象所保有的一些资源,比如已经在原对象中分配的 堆内存 , 文件描述符 , IO流 等。通常我们在声明移动构造函数时,都会使用 noexcept 关键字来修饰,这样做是为什么,有什么好处呢?

"noexcept"关键字

表示它修饰的函数不会在执行过程中抛出异常。通常使用两种不同的方式来使用这个关键字。第一种方式是将noexcept放在函数声明的后面:

这样这个函数就会被标记为不会抛出异常。 第二种方式是为noexcept提供一个常量表达式作为参数,如果这个常量表达式的值为true,那么函数就会被标记为不会抛出异常。

与通常我们使用try...catch结构来捕获异常所不同的是,使用noexcept关键字标记的函数在它抛出异常时,编译器会直接调用名为"std::terminate"的方法,来中断程序的执行,因此某种程度上可以有效阻止异常的传播和扩散。

不仅如此,在C++ 11中类结构隐式自动声明的或者是由程序员主动声明的不带有任何修饰符的析构函数,都会被编译器默认带上noexcept (true)标记,以表示这个析构函数不会抛出异常。这样做是由于,我们希望析构函数的执行只有两种结果,一种是成功的将类对象的资源释放,一种是由于某些原因,导致类资源无法被释放从而直接中断程序的运行。

抛出异常,意味着对于某种错误情况,我们不知道应该怎样处理,因此编译器将其抛给上层调用者来处理,但是析构函数的执行失败,通常会导致比如说资源泄漏或者空指针等潜在问题出现,因此相较于让程序继续运行,一个更加合理的方式是直接终止程序的运行。

另一方面要注意的是,如果一个类的父类析构函数或者它的成员函数被标记为了可抛出异常,那么这个类的析构函数就会 默认被标记为可抛出异常 ,也就我们所说的受到了污染。

接下来看一下 noexcept 关键字与 移动构造函数 之间的关系,移动构造函数在对象进行复制时通过直接移动原对象已经分配好的资源,可省去分配内存再拷贝的过程。在STL中大多数容器类型都会在调整容器大小(resize)时调用容器元素的移动构造函数来移动资源,但STL为了保证容器类型的内存安全,在大多数情况下只会调用被标记为不会抛出异常的移动构造函数,否则会调用其拷贝构造函数来作为替代。这是因为在资源的移动过程中如果抛出了异常,那么那些正在被处理的原始对象数据可能因为异常而丢失,而在拷贝构造函数中,由于进行的是资源拷贝操作,原始数据不会被更改,因此即使抛出异常也不会影响数据最终的正确性。

类似的,我们也可以通过给移动构造函数添加 noexcept 关键字的方式来将它标记为不会抛出异常,使用方式与类成员函数类似,如:

除此之外,C++ 11还为我们提供了很多标准库方法,可以用于检测类的各种构造函数状态,看下面的例子:

  • is_move_constructible 用于检测类型是否可以被移动构造,如果对应的类的移动构造函数被声明为delete,那么这个函数的实例值便为false
  • is_trivially_move_constructible 用于检测类型是否具有普通的移动构造函数,为了满足普通这一特点,我们需要保证这个类型符合多项约束条件,比如类型没有虚函数,没有虚基类,没有任何不稳定的静态成员
  • is_move_constructible 用于检测类是否具有不会抛出异常的移动构造函数

合理使用移动构造函数能够使我们开发的应用程序享受到资源移动代替资源拷贝所带来的高性能,但是不合理的使用方式就会导致应用程序的中断,甚至是会在带有诸如内存泄漏数据丢失等潜在风险的情况下继续运行,因为需要在设计类结构时提前考虑到类的各种使用场景,数据在各对象间流动方向,以及对应的处理方式。除此之外,还可以通过设置规范,也就是convention的方式来主动规避可能带来的数据和代码问题。比如说,严格禁止在代码中使用拷贝构造函数以及拷贝赋值函数,使用placement new来初始化堆对象,进而避免数据的拷贝和移动等等。

  • 人面猴 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解... 沈念sama 阅读 189,543 评论 5 赞 457
  • 死咒 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都... 沈念sama 阅读 79,630 评论 2 赞 363
  • 救了他两次的神仙让他今天三更去死 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些... 开封第一讲书人 阅读 136,876 评论 0 赞 312
  • 道士缉凶录:失踪的卖姜人 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不... 开封第一讲书人 阅读 50,742 评论 1 赞 260
  • 港岛之恋(遗憾婚礼) 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我... 茶点故事 阅读 59,769 评论 4 赞 350
  • 恶毒庶女顶嫁案:这布局不是一般人想出来的 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一... 开封第一讲书人 阅读 44,950 评论 1 赞 267
  • 城市分裂传说 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决... 沈念sama 阅读 35,665 评论 3 赞 376
  • 双鸳鸯连环套:你想象不到人心有多黑 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我... 开封第一讲书人 阅读 34,206 评论 0 赞 247
  • 万荣杀人案实录 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经... 沈念sama 阅读 38,538 评论 1 赞 283
  • 护林员之死 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日... 茶点故事 阅读 33,805 评论 2 赞 304
  • 白月光启示录 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。... 茶点故事 阅读 35,534 评论 1 赞 317
  • 活死人 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带... 沈念sama 阅读 31,415 评论 3 赞 306
  • 日本核电站爆炸内幕 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境... 茶点故事 阅读 36,834 评论 3 赞 295
  • 男人毒药:我在死后第九天来索命 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日... 开封第一讲书人 阅读 28,220 评论 0 赞 17
  • 一桩弑父案,背后竟有这般阴谋 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响... 开封第一讲书人 阅读 29,474 评论 1 赞 248
  • 情欲美人皮 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还... 沈念sama 阅读 40,522 评论 2 赞 336
  • 代替公主和亲 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚... 茶点故事 阅读 39,826 评论 2 赞 332

推荐阅读 更多精彩内容

  • C++ Primer第五版(3)——类设计者工具 3. 类设计者工具 3.1 拷贝控制 五种函数拷贝构造函数拷贝赋值运算符移动构造函数移动赋值运算符析构函数拷贝和移... 王侦 阅读 1,760 评论 0 赞 1
  • 《C++ Primer》读书笔记 前言 把《C++ Primer》[https://book.douban.com/subject/25708312... 尤汐Yogy 阅读 9,483 评论 1 赞 51
  • C++ Primer第五版(4)——高级主题 4.高级主题 4.1 标准库特殊设施 tuple类型希望将一些数据合成单一对象,但又不想麻烦地定义一个新数据结构来... 王侦 阅读 671 评论 0 赞 0
  • 2016年5月Swift 2 学习 --- 117个注意事项与要点 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的... Jenaral 阅读 2,696 评论 2 赞 9
  • C++11——拷贝控制 对拷贝控制成员使用= default 我们可以通过将拷贝控制成员定义为= default,显示地要求编译器生成它们... 铭小汁儿 阅读 854 评论 0 赞 1

cppreference.com

Noexcept specifier (since c++11).

(C++20)
(C++20)
(C++11)
(C++20)
(C++17)
(C++11)
(C++11)
General topics
(C++11)
-
-expression
block


/
(C++11)
(C++11)
(C++11)
(C++20)
(C++20)
(C++11)

expression
pointer
specifier

specifier (C++11)
specifier (C++11)
(C++11)

(C++11)
(C++11)
(C++11)
General
(C++11)
(C++20)
(C++26)
(C++11)
(C++11)
-expression
-expression
-expression
(C++11)
(C++11)
(C++17)
(C++20)
    
block
Exception specification
     specification (C++11)
     (until C++17*)
operator (C++11)

Specifies whether a function could throw exceptions.

Syntax Explanation Notes Deprecates Keywords Example Defect reports See also

[ edit ] Syntax

(1)
expression (2)
(3) (deprecated in C++17)
(removed in C++20)
expression -

[ edit ] Explanation

The noexcept-specification is not a part of the function type (just like ) and can only appear as a part of a or a top-level when declaring functions, variables, non-static data members of type function, pointer to function, reference to function, or pointer to member function, and also when declaring a parameter or a return type in one of those declarations that in turn happens to be a pointer or reference to function. It cannot appear in a or declaration.

f() noexcept; // the function f() does not throw void (*fp)() noexcept(false); // fp points to a function that may throw void g(void pfa() noexcept); // g takes a pointer to function that doesn't throw // typedef int (*pf)() noexcept; // error
(until C++17)

The noexcept-specification is a part of the function type and may appear as part of any .

(since C++17)

Every function in C++ is either non-throwing or potentially throwing :

  • potentially-throwing functions are:
(until C++17)
  • functions declared with noexcept specifier whose expression evaluates to false
  • functions declared without noexcept specifier except for
  • destructors unless the destructor of any potentially-constructed base or member is potentially-throwing (see below)
  • default constructors , copy constructors , move constructors that are implicitly-declared or defaulted on their first declaration unless
  • a constructor for a base or member that the implicit definition of the constructor would call is potentially-throwing (see below)
  • a subexpression of such an initialization, such as a default argument expression, is potentially-throwing (see below)
  • a default member initializer (for default constructor only) is potentially-throwing (see below)
  • copy assignment operators, move assignment operators that are implicitly-declared or defaulted on their first declaration unless the invocation of any assignment operator in the implicit definition is potentially-throwing (see below)
that are defaulted on their first declaration unless the invocation of any comparison operator in the implicit definition is (see below) (since C++20)
  • deallocation functions
  • non-throwing functions are all others (those with noexcept specifier whose expression evaluates to true as well as destructors, defaulted special member functions, and deallocation functions)

Explicit instantiations may use the noexcept specifier, but it is not required. If used, the exception specification must be the same as for all other declarations. A diagnostic is required only if the exception specifications are not the same within a single translation unit.

Functions differing only in their exception specification cannot be overloaded (just like the return type, exception specification is part of function type, but not part of the function signature) (since C++17) .

Pointers (including pointers to member function) to non-throwing functions can be assigned to or used to initialize (until C++17) are implicitly convertible to (since C++17) pointers to potentially-throwing functions, but not the other way around.

If a virtual function is non-throwing, all declarations, including the definition, of every overrider must be non-throwing as well, unless the overrider is defined as deleted:

Non-throwing functions are permitted to call potentially-throwing functions. Whenever an exception is thrown and the search for a handler encounters the outermost block of a non-throwing function, the function std::terminate is called:

The exception specification of a function template specialization is not instantiated along with the function declaration; it is instantiated only when needed (as defined below).

The exception-specification of an implicitly-declared special member function is also evaluated only when needed (in particular, implicit declaration of a member function of a derived class does not require the exception-specification of a base member function to be instantiated).

When the noexcept-specification of a function template specialization is needed , but hasn't yet been instantiated, the dependent names are looked up and any templates used in the expression are instantiated as if for the declaration of the specialization.

A noexcept-specification of a function is considered to be needed in the following contexts:

  • in an expression, where the function is selected by overload resolution
  • the function is odr-used
  • the function would be odr-used but appears in an unevaluated operand
  • the specification is needed to compare to another function declaration (e.g. on a virtual function overrider or on an explicit specialization of a function template)
  • in a function definition
  • the specification is needed because a defaulted special member function needs to check it in order to decide its own exception specification (this takes place only when the specification of the defaulted special member function is, itself, needed).

Formal definition of potentially-throwing expression (used to determine the default exception specification of destructors, constructors, and assignment operators as described above):

An expression e is potentially-throwing if:

  • e is a function call to a function, pointer to function, or pointer to member function which is potentially-throwing , unless e is a core constant expression (until C++17)
  • e makes an implicit call to a potentially-throwing function (such as an overloaded operator, an allocation function in a new -expression, a constructor for a function argument, or a destructor if e is a full-expression)
  • e is a throw -expression
  • e is a dynamic_cast that casts a polymorphic reference type
  • e is a typeid expression applied to a dereferenced pointer to a polymorphic type
  • e has an immediate subexpression that is potentially-throwing

[ edit ] Notes

One of the uses of the constant expression is (along with the noexcept operator ) to define function templates that declare noexcept for some types but not others.

Note that a noexcept specification on a function is not a compile-time check; it is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions. The compiler can use this information to enable certain optimizations on non-throwing functions as well as enable the noexcept operator , which can check at compile time if a particular expression is declared to throw any exceptions. For example, containers such as std::vector will move their elements if the elements' move constructor is noexcept , and copy otherwise (unless the copy constructor is not accessible, but a potentially throwing move constructor is, in which case the strong exception guarantee is waived).

[ edit ] Deprecates

noexcept is an improved version of throw ( ) , which is deprecated in C++11. Unlike pre-C++17 throw ( ) , noexcept will not call std::unexpected , may or may not unwind the stack, and will call std::terminate , which potentially allows the compiler to implement noexcept without the runtime overhead of throw ( ) . As of C++17, throw ( ) is redefined to be an exact equivalent of noexcept ( true ) .

Feature-test macro Value Std Feature
201510L (C++17) Make exception specifications be part of the type system

[ edit ] Keywords

noexcept , throw (since C++17) (until C++20)

[ edit ] Example

[ edit ] defect reports.

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
C++11 an exception specification might be eagerly instantiated it is only instantiated only if needed
C++11 a ( following noexcept might start an initializer it can only be a part of
noexcept specification
C++11 only the expression before conversion is required to be constant the conversion must also be
valid in a constant expression

[ edit ] See also

operator(C++11) determines if an expression throws any exceptions
(until C++17) specifies what exceptions are thrown by a function (deprecated in C++11)
expression signals an error and transfers control to error handler
obtains an rvalue reference if the move constructor does not throw
(function template)
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 14 August 2024, at 02:59.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

Extra Clang Tools 20.0.0git documentation

Clang-tidy - performance-noexcept-move-constructor.

«   performance-noexcept-destructor   ::   Contents   ::   performance-noexcept-swap   »

performance-noexcept-move-constructor ¶

The check flags user-defined move constructors and assignment operators not marked with noexcept or marked with noexcept(expr) where expr evaluates to false (but is not a false literal itself).

Move constructors of all the types used with STL containers, for example, need to be declared noexcept . Otherwise STL will choose copy constructors instead. The same is valid for move assignment operations.

Navigation Menu

Search code, repositories, users, issues, pull requests..., provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications You must be signed in to change notification settings

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move constructors and assignment operators should be marked as noexcept #24

@tsdgeos

tsdgeos commented Sep 30, 2019

According to

I think this is particularly important for Variant itself that sometimes is a vector of Variant

@a-maurice

muflub commented Oct 29, 2019

This should land in the next release. Thanks for the feature request.

Sorry, something went wrong.

@muflub

No branches or pull requests

@muflub

Get the Reddit app

Discussions, articles and news about the C++ programming language or programming in C++.

Should std::function's move assignment operation be noexcept?

A situation came up recently where we realised that the move assignment operator for std::function is not noexcept http://eel.is/c++draft/func.wrap.func.con#19 , despite the fact that the move constructor is (further above on that link). The std::swap for std::function is noexcept too.

I managed to find proposal P0771 that looks to change this but I'm not sure how to find the status of the proposal. That proposal suggests changing both the move construct and the move assignment operator, so presumably the move constructor was not initially noexcept .

So, I guess the question is, is this done for a reason? It seems unusual that there would be a discrepancy between the constructor and assignment operator.

By continuing, you agree to our User Agreement and acknowledge that you understand the Privacy Policy .

Enter the 6-digit code from your authenticator app

You’ve set up two-factor authentication for this account.

Enter a 6-digit backup code

Create your username and password.

Reddit is anonymous, so your username is what you’ll go by here. Choose wisely—because once you get a name, you can’t change it.

Reset your password

Enter your email address or username and we’ll send you a link to reset your password

Check your inbox

An email with a link to reset your password was sent to the email address associated with your account

Choose a Reddit account to continue

MC++ BLOG

C++ Core Guidelines: The noexcept Specifier and Operator

If you skim the remaining rules to error handling, you often read the word  noexcept . Before I write about the rules for error handling, I will write about the noexcept specifier and the noexcept operator in this post. 

teddy 562960 1280

noexcept exists in two forms since C++11: as a specifier and as an operator. The C++ core guidelines use the specifier.

noexcept as specifier

By declaring a function, a method, or a lambda function as noexcept , you specify that these do not throw an exception, and if they throw, you do not care and let the program crash. For simplicity reasons, I will write about function but also mean methods and function templates. There are various ways to express your intention:

The noexcept specification is equivalent to the noexcept(true) specification. throw( ) is equivalent to noexcept(tru e) but was deprecated with C++11 and will be removed with C++20. In contrast, noexcept(false) means that the function may throw an exception. The noexcept specification is part of the function type but can not be used for function overloading. 

There are two good reasons for using noexcept : First, an exception specifier documents the function’s behavior. If a function is specified as noexcept , it can be safely used in a non-throwing function. Second, it is an optimization opportunity for the compiler. noexcept may not call std::unexpected and may not unwind the stack. The initialization of a container may cheaply move the elements into the container if the move constructor is declared as noexcept. If not declared as noexcept, the elements may be expensive copied into the container.

Each function in C++ is either non-throwing or potentially throwing. Potentially throwing means:

  • The function may use a function that may throw.
  • The function is declared without a  noexcept specification.
  • The function uses a dynamic_cast to a reference type.

There is an exception to rule 2, that functions are potentially throwing if they have no noexcept specification. These exceptions include the following six special member functions. They are implicitly non-throwing.

Modernes C++ Mentoring

Be part of my mentoring programs:

  • " Fundamentals for C++ Professionals " (open)
  • " Design Patterns and Architectural Patterns with C++ " (open)
  • " C++20: Get the Details " (open)
  • " Concurrency with Modern C++ " (open)

Do you want to stay informed: Subscribe.

  • Default constructor and destructor
  • Move and copy constructor
  • Move and copy assignment operator

This special six member such as the destructor, can only be non-throwing if all destructors of the attributes and the bases-classes are non-throwing. Of course, the corresponding statement will hold for the five other special member functions.

What happens when you throw an exception in a function declared non-throwing? In this case, std::terminate is called. std::terminate calls the currently installed std::terminate_handler which calls std::abort  by default.The result is an abnormal program termination.

For completeness, is want to present  noexcept as operator.

noexcept as operator

The noexcept operator checks at compile-time if an expression does not throw an exception. The noexcept operator does not evaluate the expression. It can be used in a noexcept specifier of a function template to declare that the function may throw exceptions depending on the current type.

To make my description clear, here is a simple example of a function template that copies its return value.

Of course, the most exciting line in this example is line (1). In particular, the expression noexcept(noexcept(T(src)). The inner noexcept ist the noexcept operator, and the outer is the noexcept specifier. The expression noexcept(T(src)) checks if the copy constructor is non-throwing . This is the case for the class Noexcept (2) but not for the class NonNoexcept (3) b ecause of the copy constructor of  std::vector  that may throw . Consequently, expression (4) returns true , and expression (5) returns false.

noexceptOperator

Maybe you know about it. You can check at compile time with the help of the type traits library if a type T has a non-throwing copy constructor: std::is_nothrow_copy_constructible::value . Based on this predicate, you can use instead of the noexcept operator the predicate from the type traits library:

I don’t know which version of copy do you prefer. I prefer the type traits version because it is more expressive.

The following rule is about the noexcept specifier.

E.12: Use noexcept when exiting a function because of a throw is impossible or unacceptable

The title of this rule may be a little bit confusing. It says that you should declare a function as noexcept, if

  • it does not throw or
  • you don’t care in case of an exception. You are willing to crash the program because you can not handle an exception such as std::bad_alloc due to memory exhaustion.

 It’s not a good idea to throw an exception if you are the direct owner of an object.

E.13: Never throw while being the direct owner of an object

Here is an example to direct ownership from the guidelines:

If the throw is fired, the memory is lost, and you leak. The simple solution is to remove the ownership and make the C++ runtime to the direct owner of the object. Just create a local object or at least a guard as a local object. And you know the C++ runtime takes care of local objects. Here are three variations of this idea.

p1 is locally created, but p2 and p3 are kinds of guards for the objects. The std::vector uses the heap to manage its data. Additionally, with all three variations, you eliminate the delete call.

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

  • C++ – The Core Language
  • C++ – The Standard Library
  • C++ – Compact
  • C++11 and C++14
  • Concurrency with Modern C++
  • Design Pattern and Architectural Pattern with C++
  • Embedded Programming with Modern C++
  • Generic Programming (Templates) with C++
  • Clean Code with Modern C++

Online Seminars (German)

  • Embedded Programmierung mit modernem C++   (24. Sep. 2024 bis 26. Sep. 2024)
  • Mobil: +49 176 5506 5086
  • Mail: [email protected]
  • German Seminar Page: www.ModernesCpp.de
  • Mentoring Page: www.ModernesCpp.org

Modernes C++ Mentoring,

move assignment operators should be marked noexcept

Leave a Reply

Leave a reply cancel reply.

Your email address will not be published. Required fields are marked *

Design by contract

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Does noexcept matter with explicitly defaulted move constructor/assignment operator?

As far as I know, if move constructor/assignment operator are either implicitly generated or explicitly defaulted by user (1) , the compiler will decide whether these special member functions should be noexcept or not depending on whether all the members of a class provide noexcept guarantees for move operations. But what if I want to use default move special members and force them to be noexcept regardless of the underlying members exception guarantees for move operations? Is there any difference for the compiler between (1) and (2) declarations?

  • move-semantics

Alexey104's user avatar

  • 2 Yes it matters... moving with noexcept can be optimized by the compiler (specialy true when moving in containers like in std::sort) –  Pepijn Kramer Commented Jan 15 at 6:32

Ok, I found the answer in Nico's Josuttis book "C++ Move Semantics - The Complete Guide":

When you have a defaulted special member function you can explicitly specify a different noexcept guarantee than the generated one. For example: class C { ... public: C(const C&) noexcept = default; // guarantees not to throw (OK since C++20) C(C&&) noexcept(false) = default; // specifies that it might throw (OK since C++20) ... }; Before C++20, if the generated and specified noexcept condition contradict, the defined function was deleted.

I asked this question because I want STL algorithms to always apply move semantics to my classes regardless of their members' exception guarantees, and I am ready to deal with std::abort if something goes wrong. But it seems that prior to C++ 20 the only way to force noexcept guarantees on move special member functions was to explicitly define them, even if you don't need your own implementation. It turns out C++20 solved this by allowing us to specify noexcept guarantees for defaulted special member functions. Of course, as in case with any other noexcept function, if any of the members of a class throws during a move operation, std::abort will be called if move constructor/assignment operator are declared noexcept for that class, as it was kindly pointed out by @MichaëlRoy in the comments section.

Mark Rotteveel's user avatar

  • 2 @Alexey104. This means that for a move constructor, the default noexcept condition is equal to noexcept(noexcept(X::X(X&&)...); where X... are the types of the members of your class. So, if you specify noexcept, and one of you data members' constructor throws, your program will perform a hard exit. This definitely is worth mentioning in your answer, since before c++20, this kind of behavior was not possible. –  Michaël Roy Commented Jan 15 at 11:00
  • 3 I meant noexcept(noexcept(X::X(X&&) && ...) sorry for the typo. –  Michaël Roy Commented Jan 15 at 11:04
  • 2 @MichaëlRoy > "So, if you specify noexcept, and one of you data members' constructor throws, your program will perform a hard exit." Yes, I understand that, and I intentionally want this behavior. I want STL algorithms to always apply move semantics to my classes regardless of of their members' exception guarantees, and I accept std::abort if something goes wrong. Thank you for the clarification. –  Alexey104 Commented Jan 15 at 11:17
  • 5 Perhaps mention this behavior in the answer for others reading this Q&A. –  Sebastian Commented Jan 15 at 11:19
  • 1 @Alexey104 Cool. I pointed it out because I also think it's worth mentioning in your answer. –  Michaël Roy Commented Jan 15 at 16:43

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c++ move-semantics noexcept or ask your own question .

  • The Overflow Blog
  • Where does Postgres fit in a world of GenAI and vector databases?
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • What does a new user need in a homepage experience on Stack Overflow?
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • Staging Ground Reviewer Motivation

Hot Network Questions

  • What does it say in the inscriptions on Benjamin's doorway; A Canticle for Leibowitz
  • Reusing own code at work without losing licence
  • How can judicial independence be jeopardised by politicians' criticism?
  • Purpose of burn permit?
  • My school wants me to download an SSL certificate to connect to WiFi. Can I just avoid doing anything private while on the WiFi?
  • How can I get an Edge's Bevel Weight attribute value via Python?
  • Walk or Drive to school?
  • I'm trying to remember a novel about an asteroid threatening to destroy the earth. I remember seeing the phrase "SHIVA IS COMING" on the cover
  • Can a 2-sphere be squashed flat?
  • My visit is for two weeks but my host bought insurance for two months is it okay
  • Does Vexing Bauble counter taxed 0 mana spells?
  • Integral concerning the floor function
  • Why is one of the Intel 8042 keyboard controller outputs inverted?
  • Meaning of "blunk"
  • The answer is not wrong
  • Exact time point of assignment
  • Variable usage in arithmetic expansions
  • How to attach a 4x8 plywood to a air hockey table
  • Is it true that weeds prefer poor soil?
  • How do you say "head tilt“ in Chinese?
  • Could someone tell me what this part of an A320 is called in English?
  • How would increasing atomic bond strength affect nuclear physics?
  • What are the French verbs that have invariable past participles?
  • Migrate SBS 2008 to 2019

move assignment operators should be marked noexcept

COMMENTS

  1. c++11

    @Klaus, for the OP's examples the compiler can already see that those operations don't throw, adding noexcept tells it nothing. In general, if the function definition is visible and suitable for inlining then the compiler has all the information it needs to make that decision anyway, without noexcept.Any advantages in codegen (such as not needing to generate unwinding info) applies to all ...

  2. Are move constructors required to be noexcept?

    It seems that std::vector in particular is picky about whether or not you declare your move constructors with noexcept. If you do, then std::vector will use them. If you don't then std::vector will resort to using your copy constructor instead. At least in some cases. Notably whenever it reshuffles items internally, after an internal array resize.

  3. 22.3

    Move constructors and move assignment should be marked as noexcept. This tells the compiler that these functions will not throw exceptions. We introduce noexcept in lesson 27.9 -- Exception specifications and noexcept and discuss why move constructors and move assignment are marked as noexcept in lesson 27.10 -- std::move_if_noexcept.

  4. Move assignment operator

    The move assignment operator is called whenever it is selected by overload resolution, e.g. when an object appears on the left-hand side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.. Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors ...

  5. Move Constructors and Move Assignment Operators (C++)

    This topic describes how to write a move constructor and a move assignment operator for a C++ class. A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: &&. This topic builds upon the following C++ class ...

  6. Move constructors

    Triviality of eligible move constructors determines whether the class is an implicit-lifetime type, and whether the class is a trivially copyable type. [] NoteTo make the strong exception guarantee possible, user-defined move constructors should not throw exceptions. For example, std::vector relies on std::move_if_noexcept to choose between move and copy when the elements need to be relocated.

  7. Friendly reminder to mark your move constructors noexcept -- AndyG

    Friendly reminder to mark your move constructors noexcept. by AndyG. From the article: Since C++11 we have had the noexcept keyword, which is a promise that the function will not throw an exception (and if it does, go straight to std::terminate, do not pass go). noexcept is nice for two reasons: The compiler can optimize a little better because ...

  8. 27.10

    Warning. If a type has both potentially throwing move semantics and deleted copy semantics (the copy constructor and copy assignment operator are unavailable), then std::move_if_noexcept will waive the strong guarantee and invoke move semantics. This conditional waiving of the strong guarantee is ubiquitous in the standard library container classes, since they use std::move_if_noexcept often.

  9. std::move in Utility in C++

    In C+, the move assignment operator is used to transfer the ownership of the resources from one object to another when the object is assigned some rvalue references or using std::move. It allows efficient memory manipulation by avoiding unnecessary copies of the objects. In this article, we will learn how to implement a move assignment operator in

  10. Move Assignment Operator in C++ 11

    The move assignment operator was added in C++ 11 to further strengthen the move semantics in C++. It is like a copy assignment operator but instead of copying the data, this moves the ownership of the given data to the destination object without making any additional copies. The source object is left in a valid but unspecified state.

  11. C++中为什么move construct需要加noexcept

    C++中为什么move construct需要加noexcept. C++ 11中增加了名为移动构造函数的构造函数类型。通过使用移动构造函数,我们可以在进行对象复制时直接"窃取"拷贝对象所保有的一些资源,比如已经在原对象中分配的堆内存,文件描述符,IO流等。通常我们在声明移动构造函数时,都会使用 noexcept 关键字来 ...

  12. noexcept specifier (since C++11)

    The noexcept-specification is a part of the function type and may appear as part of any function declarator . (since C++17) Every function in C++ is either non-throwing or potentially throwing : potentially-throwing functions are: functions declared with a non-empty dynamic exception specification. (until C++17)

  13. performance-noexcept-move-constructor

    Move constructors of all the types used with STL containers, for example, need to be declared noexcept. Otherwise STL will choose copy constructors instead. The same is valid for move assignment operations. «

  14. Any best-practice guidelines on move-assignment operator & self

    Just use the move-and-swap idiom. T& operator=(T t) noexcept { //swap each member with t return *this; } Pros: Serves both as move-assignment and copy-assignment, if there is a copy constructor. Reuse the code from the move-constructor Can be marked noexcept (provided that the swap is noexcept, that is in 99% of the cases).

  15. Move constructors and assignment operators should be marked as noexcept

    Move constructors and assignment operators should be marked as noexcept #24. Closed tsdgeos opened this issue Sep 30, 2019 · 1 comment ... need to be declared noexcept. Otherwise STL will choose copy constructors instead. The same is valid for move assignment operations. I think this is particularly important for Variant itself that sometimes ...

  16. PDF std::function move constructor should be noexcept

    operator behaves as a copy assignment under certain conditions, making the noexcept guarantee impossible. In general, algorithmic efficiency can be improved if the move constructor and swap functions are noexcept, as they would be with this proposal. A much smaller set of algorithms benefit from a noexcept move-assignment operator.

  17. Should std::function's move assignment operation be noexcept?

    The std::swap for std::function is noexcept too. I managed to find proposal P0771 that looks to change this but I'm not sure how to find the status of the proposal. That proposal suggests changing both the move construct and the move assignment operator, so presumably the move constructor was not initially noexcept.

  18. Why aren't container move assignment operators noexcept?

    The move assignment operator in container classes is defined to be noexcept because many containers are designed to implement the strong exception safety guarantee. Containers implement the strong exception safety guarantee because back before there were move assignment operators, the container had to be copied.

  19. C++ Core Guidelines: The noexcept Specifier and Operator

    In particular, the expression noexcept (noexcept (T (src)). The inner noexcept ist the noexcept operator, and the outer is the noexcept specifier. The expression noexcept (T (src)) checks if the copy constructor is non-throwing. This is the case for the class Noexcept (2) but not for the class NonNoexcept (3) b ecause of the copy constructor of ...

  20. Does noexcept matter with explicitly defaulted move constructor

    Ok, I found the answer in Nico's Josuttis book "C++ Move Semantics - The Complete Guide": When you have a defaulted special member function you can explicitly specify a different noexcept guarantee than the generated one.