/ | ||||
(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 | ||||
/ types | ||||
types | ||||
Members | ||||
pointer | ||||
-declarations | ||||
(C++11) | ||||
specifier | ||||
specifier | ||||
Special member functions | ||||
(C++11) | ||||
(C++11) | ||||
Inheritance | ||||
specifier (C++11) | ||||
specifier (C++11) |
A move assignment operator is a non-template non-static member function with the name operator = that can be called with an argument of the same class type and copies the content of the argument, possibly mutating the argument.
Syntax Explanation Implicitly-declared move assignment operator Implicitly-defined move assignment operator Deleted move assignment operator Trivial move assignment operator Eligible move assignment operator Notes Example Defect reports See also |
For the formal move assignment operator syntax, see function declaration . The syntax list below only demonstrates a subset of all valid move assignment operator syntaxes.
return-type parameter-list | (1) | ||||||||
return-type parameter-list function-body | (2) | ||||||||
return-type parameter-list-no-default | (3) | ||||||||
return-type parameter-list | (4) | ||||||||
return-type class-name parameter-list function-body | (5) | ||||||||
return-type class-name parameter-list-no-default | (6) | ||||||||
class-name | - | the class whose move assignment operator is being declared, the class type is given as in the descriptions below |
parameter-list | - | a of only one parameter, which is of type , const T&&, volatile T&& or const volatile T&& |
parameter-list-no-default | - | a of only one parameter, which is of type , const T&&, volatile T&& or const volatile T&& and does not have a default argument |
function-body | - | the of the move assignment operator |
return-type | - | any type, but is favored in order to allow chaining asssignments |
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, TCP sockets, I/O streams, running threads, etc.), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state. For example, move-assigning from a std::string or from a std::vector may result in the argument being left empty. This is not, however, a guarantee. A move assignment is less, not more restrictively defined than ordinary assignment; where ordinary assignment must leave two copies of data at completion, move assignment is required to leave only one.
If no user-defined move assignment operators are provided for a class type, and all of the following is true:
then the compiler will declare a move assignment operator as an inline public member of its class with the signature T & T :: operator = ( T && ) .
A class can have multiple move assignment operators, e.g. both T & T :: operator = ( const T && ) and T & T :: operator = ( T && ) . If some user-defined move assignment operators are present, the user may still force the generation of the implicitly declared move assignment operator with the keyword default .
The implicitly-declared (or defaulted on its first declaration) move assignment operator has an exception specification as described in dynamic exception specification (until C++17) noexcept specification (since C++17) .
Because some assignment operator (move or copy) is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
If the implicitly-declared move assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used or needed for constant evaluation (since C++14) .
For union types, the implicitly-defined move assignment operator copies the object representation (as by std::memmove ).
For non-union class types, the move assignment operator performs full member-wise move assignment of the object's direct bases and immediate non-static members, in their declaration order, using built-in assignment for the scalars, memberwise move-assignment for arrays, and move assignment operator for class types (called non-virtually).
The implicitly-defined move assignment operator for a class is if is a , and that is of class type (or array thereof), the assignment operator selected to move that member is a constexpr function. | (since C++14) (until C++23) |
The implicitly-defined move assignment operator for a class is . | (since C++23) |
As with copy assignment, it is unspecified whether virtual base class subobjects that are accessible through more than one path in the inheritance lattice, are assigned more than once by the implicitly-defined move assignment operator:
The implicitly-declared or defaulted move assignment operator for class T is defined as deleted if any of the following conditions is satisfied:
A deleted implicitly-declared move assignment operator is ignored by overload resolution .
The move assignment operator for class T is trivial if all of the following is true:
A trivial move assignment operator performs the same action as the trivial copy assignment operator, that is, makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially move-assignable.
A move assignment operator is eligible if it is not deleted. | (until C++20) |
A move assignment operator is eligible if all following conditions are satisfied: (if any) are satisfied. than any other move assignment operator. | (since C++20) |
Triviality of eligible move assignment operators determines whether the class is a trivially copyable type .
If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either a prvalue such as a nameless temporary or an xvalue such as the result of std::move ), and selects the copy assignment if the argument is an lvalue (named object or a function/operator returning lvalue reference). If only the copy assignment is provided, all argument categories select it (as long as it takes its argument by value or as reference to const, since rvalues can bind to const references), which makes copy assignment the fallback for move assignment, when move is unavailable.
It is unspecified whether virtual base class subobjects that are accessible through more than one path in the inheritance lattice, are assigned more than once by the implicitly-defined move assignment operator (same applies to copy assignment ).
See assignment operator overloading for additional detail on the expected behavior of a user-defined move-assignment operator.
[ 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 | the conditions where defaulted move assignment operators are defined as deleted did not consider multi-dimensional array types | consider these types | |
C++11 | a defaulted move assignment operator that would call a non-trivial copy assignment operator was deleted; a defaulted move assignment operator that is deleted still participated in overload resolution | allows call to such copy assignment operator; made ignored in overload resolution | |
C++11 | specification for a defaulted move assignment operator involving a virtual base class was missing | added | |
C++11 | a volatile subobject made of a defaulted move assignment operator non-trivial ( ) | triviality not affected | |
C++11 | a defaulted move assignment operator for class was not defined as deleted if is abstract and has non-move-assignable direct virtual base classes | the operator is defined as deleted in this case | |
C++20 | a move assignment operator was not eligible if there is another move assignment operator which is more constrained but does not satisfy its associated constraints | it can be eligible in this case | |
C++11 | the implicitly-defined move assignment operator for union types did not copy the object representation | they copy the object representation |
Prerequisites:
References:
In C++ there are two types of references-
Move Constructor And Semantics:
The move constructor was introduced in C++11 . The need or purpose of a move constructor is to steal or move as many resources as it can from the source (original) object , as fast as possible, because the source does not need to have a meaningful value anymore, and/or because it is going to be destroyed in a moment anyway. So that one can avoid unnecessarily creating copies of an object and make efficient use of the resources
While one can steal the resources, but one must leave the source (original) object in a valid state where it can be correctly destroyed.
Move constructors typically “steal” the resource of the source (original) object rather than making several copies of them, and leaves the source object in a “valid but unspecified state”.
The copy constructor uses the lvalue references which are marked with one ampersand (&) while the move constructor uses the rvalue references are marked with two ampersands (&&).
std::move() is a function used to convert an lvalue reference into the rvalue reference. Used to move the resources from a source object i.e. for efficient transfer of resources from one object to another. std::move() is defined in the <utility> header .
template< class T > typename std::remove_reference<T>::type&& move(T&& t) noexcept; (since C++11)(until C++14) template< class T > constexpr std::remove_reference_t<T>&& move(T&& t) noexcept (since C++14)
Example: Below is the C++ program to show what happens without using move semantics i.e. before C++11.
Explanation:
Assuming the program is compiled and executed using a compiler that doesn’t support move semantics. In the main() function,
1. std::vector<std::string> vecString;- An empty vector is created with no elements in it. 2. vecString = createAndInsert();- The createAndInsert() function is called. 3. In createAndInsert() function-
Note: Here, we unnecessarily allocate & deallocate the memory of the temporary string object. which can be optimized (improved) further just by moving the data from the source object.
Example: Below is the C++ program to implement the above concept using move semantics i.e. since C++11 and later.
Here, in order to use the move semantics. The compiler must support the C++11 standards or above. The story of execution for the main() function and createAndInsert() function remains the same till the line vec.push_back( str );
A question may arise why the temporary object is not moved to vector vec using std::move(). The reason behind it is the push_back() method of the vector. Since C++11 the push_back() method has been provided with its new overloaded version.
The push_back() method takes its parameter by const reference, but since std::vector stores its elements by value, a deep copy of str is created and inserted into the vector. This involves calling the copy constructor of std::string.
Syntax:
constexpr void push_back(const T& value); (since C++20) void push_back(T&& value); (since C++11) (until C++20) void push_back(const T& value); (until C++20) constexpr void push_back(T&& value); (since C++20)
A question may arise while returning the vec object to its caller. As it is not required anymore and also a whole temporary object of a vector is going to be created and also local vector vec will be destroyed, then why std::move() is not used to steal the value and return it. Its answer is simple and obvious, there is optimization at the compiler level known as (Named) Return Value Object, more popularly known as RVO .
Some Fallback Of Move Semantics:
Note: The foo() function have all necessary types of arguments.
Below is the C++ program to implement all the above concepts-
Summary:
Similar reads.
string (1) | |
---|---|
c-string (2) | |
character (3) |
string (1) | |
---|---|
c-string (2) | |
character (3) | |
initializer list (4) | |
move (5) |
main () { std::string str1, str2, str3; str1 = ; str2 = ; str3 = str1 + str2; std::cout << str3 << ; 0; } |
Exception safety.
Replaces the contents of the string.
(1) Copy assignment operator. Replaces the contents with a copy of the contents of other .
If *this and str are the same object, this function has no effect.
(2) Move assignment operator. Replaces the contents with those of other using move semantics (i.e. the data in other is moved from other into this container).
other is in a valid but unspecified state afterwards.
If std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value is true , the allocator of *this is replaced by a copy of that of str .
If it is false and the allocators of *this and str do not compare equal, *this cannot take ownership of the memory owned by str and must assign each character individually, allocating additional memory using its own allocator as needed.
Unlike other container move assignments, references , pointers , and iterators to str may be invalidated.
(3) Replaces the contents with those of null-terminated character string pointed to by s as if by assign(s, Traits::length(s)) .
(4) Replaces the contents with character ch as if by assign(std::addressof(ch), 1) .
(5) Replaces the contents with those of the initializer list ilist as if by assign(ilist.begin(), ilist.size()) .
(6) Implicitly converts t to a string view sv as if by std::basic_string_view<CharT, Traits> sv = t; , then replaces the contents with those of the sv as if by assign(sv) .
This overload participates in overload resolution only if std::is_convertible_v<const StringViewLike&, std::basic_string_view<CharT, Traits>> is true and std::is_convertible_v<const StringViewLike&, const CharT*> is false .
(7) Deleted constructor for std::nullptr_t makes it so that std::string cannot be assigned from nullptr .
Complexity .
If the operation would result in size() > max_size() , throws std::length_error .
IMAGES
COMMENTS
for (auto _ : state) {. str = base; } } BENCHMARK(string_assign_operator); Here is the graphical comparitive solution. It seems like both the methods are equally faster. The assignment operator has better results. Use string::assign only if a specific position from the base string has to be assigned.
std::string a = std::string( "simple_text" ); At first a temporary object is created std::string ( "simple_text" ); with using constructor with parameter const char * and then this object is moved into a by using the move constructor. However the C++ Standard allows to eliminate the call of the move constructor.
basic_string& operator=(std::nullptr_t)= delete; (7) (since C++23) Replaces the contents of the string. 1) Replaces the contents with a copy of str. If *this and str are the same object, this function has no effect. 2) Replaces the contents with those of str using SequenceContainer 's move assignment semantics.
22.5 — std::string assignment and swapping. Alex September 16, 2022. String assignment. The easiest way to assign a value to a string is to use the overloaded operator= function. There is also an assign () member function that duplicates some of this functionality. string& string::operator= (const string& str)
Does s.assign allocate a new buffer and copy the string into it or it assumes ownership of the pointer; The STL string method assign will copy the character array into the string. If the already allocated buffer inside the string is insufficient it will reallocate the memory internally. The STL string will not take ownership of the original array.
Assigns a new value to the string, replacing its current contents. (1) string Copies str. (2) substring Copies the portion of str that begins at the character position subpos and spans sublen characters (or until the end of str, if either str is too short or if sublen is string::npos). (3) c-string Copies the null-terminated character sequence (C-string) pointed by s.
The member function assign () is used for the assignments, it assigns a new value to the string, replacing its current contents. Syntax 1: Assign the value of string str. string& string::assign (const string& str) str : is the string to be assigned. Returns : *this.
for assignments to class type objects, the right operand could be an initializer list only when the assignment is defined by a user-defined assignment operator. removed user-defined assignment constraint. CWG 1538. C++11. E1 ={E2} was equivalent to E1 = T(E2) ( T is the type of E1 ), this introduced a C-style cast. it is equivalent to E1 = T{E2}
In those situations where copy assignment cannot benefit from resource reuse (it does not manage a heap-allocated array and does not have a (possibly transitive) member that does, such as a member std::vector or std::string), there is a popular convenient shorthand: the copy-and-swap assignment operator, which takes its parameter by value (thus working as both copy- and move-assignment ...
Assigns a new value to the string, replacing its current contents. (See member function assign for additional assignment options). Parameters str A string object, whose value is either copied (1) or moved (5) if different from *this (if moved, str is left in an unspecified but valid state). s Pointer to a null-terminated sequence of characters.
Strings are objects that represent sequences of characters. The standard string class provides support for such objects with an interface similar to that of a standard container of bytes, but adding features specifically designed to operate with strings of single-byte characters. The string class is an instantiation of the basic_string class template that uses char (i.e., bytes) as its ...
21.12 — Overloading the assignment operator. Alex July 22, 2024. The copy assignment operator (operator=) is used to copy values from one object to another already existing object. As of C++11, C++ also supports "Move assignment". We discuss move assignment in lesson 22.3 -- Move constructors and move assignment .
So that is the long way around of doing it. But there is a technique called the copy and swap idiom. That automates Step 1 and Step 3. So all you have to do is write Step 2. string& string::operator=(string strInstance) {. std::swap(strInstance.pcString, pcString); this->iCapacity = strInstance.iCapacity;
the copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial. A trivial copy assignment operator makes a copy of the object representation as if by std::memmove. All data types compatible with the C language (POD types) are trivially copy-assignable.
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 ...
A string object, whose value is copied at the end. s. Pointer to a null-terminated sequence of characters. The sequence is copied at the end of the string. c. A character, which is appended to the current value of the string. il. An initializer_list object.
In C++, the assignment operator forms the backbone of many algorithms and computational processes by performing a simple operation like assigning a value to a variable. ... they serve different requirements. In this article, we will look at some major differences between the std::wstring and std::string in C++. Wide String in C++The std ...
Assigns a new value to the string, replacing its current contents. (See member function assign for additional assignment options). Parameters str A basic_string object of the same type (with the same class template arguments charT, traits and Alloc), whose value is either copied (1) or moved (5) if different from *this (if moved, str is left in an unspecified but valid state).
(7) Deleted constructor for std::nullptr_t makes it so that std::string cannot be assigned from nullptr. Parameters . ch - value to initialize characters of the string with; str - string to be used as source to initialize the string with; s - pointer to a null-terminated character string to use as source to initialize the string with; ilist - std::initializer_list to initialize the string with