• Sign In / Suggest an Article

Current ISO C++ status

Upcoming ISO C++ meetings

Upcoming C++ conferences

Compiler conformance status

ISO C++ committee meeting

June 24-29, St. Louis, MO, USA

July 2-5, Folkestone, Kent, UK

Quick Q: Most concise way to disable copy and move semantics

By Adrien Hamelin | Feb 20, 2018 08:40 AM | Tags: c++11 advanced

Quick A: Delete the move assignment.

Recently on SO:

Most concise way to disable copy and move semantics According to this chart (by Howard Hinnant): The most concise way is to =delete move assignment operator (or move constructor, but it can cause problems mentioned in comments). Though, in my opinion the most readable way is to =delete both copy constructor and copy assignment operator.

Share this Article

Add a comment, comments (0).

There are currently no comments on this entry.

Copy assignment operator

A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . For a type to be CopyAssignable , it must have a public copy assignment operator.

Explanation

  • Typical declaration of a copy assignment operator when copy-and-swap idiom can be used.
  • Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used (non-swappable type or degraded performance).
  • Forcing a copy assignment operator to be generated by the compiler.
  • Avoiding implicit copy assignment.

The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.

Implicitly-declared copy assignment operator

If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:

  • each direct base B of T has a copy assignment operator whose parameters are B or const B & or const volatile B & ;
  • each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M & or const volatile M & .

Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument.)

A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)

The implicitly-declared (or defaulted on its first declaration) copy assignment operator has an exception specification as described in dynamic exception specification (until C++17) exception specification (since C++17)

Because the copy assignment operator 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.

Deleted implicitly-declared copy assignment operator

A implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:

  • T has a user-declared move constructor;
  • T has a user-declared move assignment operator.

Otherwise, it is defined as defaulted.

A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:

  • T has a non-static data member of non-class type (or array thereof) that is const ;
  • T has a non-static data member of a reference type;
  • T has a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);
  • T is a union-like class , and has a variant member whose corresponding assignment operator is non-trivial.

Trivial copy assignment operator

The copy assignment operator for class T is trivial if all of the following is true:

  • it is not user-provided (meaning, it is implicitly-defined or defaulted) , , and if it is defaulted, its signature is the same as implicitly-defined (until C++14) ;
  • T has no virtual member functions;
  • T has no virtual base classes;
  • the copy assignment operator selected for every direct base of T is trivial;
  • 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.

Implicitly-defined copy assignment operator

If the implicitly-declared copy 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 . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.

The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.

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 copy assignment operator (same applies to move assignment ).

See assignment operator overloading for additional detail on the expected behavior of a user-defined copy-assignment operator.

Defect reports

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

Copy assignment operator

A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . A type with a public copy assignment operator is CopyAssignable .

[ edit ] Syntax

[ edit ] explanation.

  • Typical declaration of a copy assignment operator when copy-and-swap idiom can be used
  • Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used
  • Forcing a copy assignment operator to be generated by the compiler
  • Avoiding implicit copy assignment

The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.

[ edit ] Implicitly-declared copy assignment operator

If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:

  • each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B &
  • each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M &

Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument)

A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default .

Because the copy assignment operator 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.

[ edit ] Deleted implicitly-declared copy assignment operator

The implicitly-declared or defaulted copy assignment operator for class T is defined as deleted in any of the following is true:

  • T has a non-static data member that is const
  • T has a non-static data member of a reference type.
  • T has a non-static data member that cannot be copy-assigned (has deleted, inaccessible, or ambiguous copy assignment operator)
  • T has direct or virtual base class that cannot be copy-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
  • T has a user-declared move constructor
  • T has a user-declared move assignment operator

[ edit ] Trivial copy assignment operator

The implicitly-declared copy assignment operator for class T is trivial if all of the following is true:

  • T has no virtual member functions
  • T has no virtual base classes
  • The copy assignment operator selected for every direct base of T is trivial
  • The copy assignment operator selected for every non-static class type (or array of class type) memeber 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.

[ edit ] Implicitly-defined copy assignment operator

If the implicitly-declared copy assignment operator is not deleted or trivial, it is defined (that is, a function body is generated and compiled) by the compiler. For union types, the implicitly-defined copy assignment copies the object representation (as by std:: memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using, using built-in assignment for the scalars and copy assignment operator for class types.

The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.

[ edit ] Notes

If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either prvalue such as a nameless temporary or xvalue such as the result of std:: move ), and selects the copy assignment if the argument is 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.

[ edit ] Copy and swap

Copy assignment operator can be expressed in terms of copy constructor, destructor, and the swap() member function, if one is provided:

T & T :: operator = ( T arg ) { // copy/move constructor is called to construct arg     swap ( arg ) ;     // resources exchanged between *this and arg     return * this ; }   // destructor is called to release the resources formerly held by *this

For non-throwing swap(), this form provides strong exception guarantee . For rvalue arguments, this form automatically invokes the move constructor, and is sometimes referred to as "unifying assignment operator" (as in, both copy and move).

[ edit ] Example

This browser is no longer supported.

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

Explicitly Defaulted and Deleted Functions

  • 8 contributors

In C++11, defaulted and deleted functions give you explicit control over whether the special member functions are automatically generated. Deleted functions also give you simple language to prevent problematic type promotions from occurring in arguments to functions of all types—special member functions, and normal member functions and nonmember functions—which would otherwise cause an unwanted function call.

Benefits of explicitly defaulted and deleted functions

In C++, the compiler automatically generates the default constructor, copy constructor, copy-assignment operator, and destructor for a type if it doesn't declare its own. These functions are known as the special member functions , and they're what make simple user-defined types in C++ behave like structures do in C. That is, you can create, copy, and destroy them without extra coding effort. C++11 brings move semantics to the language and adds the move constructor and move-assignment operator to the list of special member functions that the compiler can automatically generate.

This is convenient for simple types, but complex types often define one or more of the special member functions themselves, and this can prevent other special member functions from being automatically generated. In practice:

If any constructor is explicitly declared, then no default constructor is automatically generated.

If a virtual destructor is explicitly declared, then no default destructor is automatically generated.

If a move constructor or move-assignment operator is explicitly declared, then:

No copy constructor is automatically generated.

No copy-assignment operator is automatically generated.

If a copy constructor, copy-assignment operator, move constructor, move-assignment operator, or destructor is explicitly declared, then:

No move constructor is automatically generated.

No move-assignment operator is automatically generated.

Additionally, the C++11 standard specifies the following additional rules:

  • If a copy constructor or destructor is explicitly declared, then automatic generation of the copy-assignment operator is deprecated.
  • If a copy-assignment operator or destructor is explicitly declared, then automatic generation of the copy constructor is deprecated.

In both cases, Visual Studio continues to automatically generate the necessary functions implicitly, and doesn't emit a warning by default. Since Visual Studio 2022 version 17.7, C5267 can be enabled to emit a warning.

The consequences of these rules can also leak into object hierarchies. For example, if for any reason a base class fails to have a default constructor that's callable from a deriving class—that is, a public or protected constructor that takes no parameters—then a class that derives from it can't automatically generate its own default constructor.

These rules can complicate the implementation of what should be straight-forward, user-defined types and common C++ idioms—for example, making a user-defined type noncopyable by declaring the copy constructor and copy-assignment operator privately and not defining them.

Before C++11, this code snippet was the idiomatic form of noncopyable types. However, it has several problems:

The copy constructor has to be declared privately to hide it, but because it's declared at all, automatic generation of the default constructor is prevented. You have to explicitly define the default constructor if you want one, even if it does nothing.

Even if the explicitly defined default constructor does nothing, the compiler considers it to be nontrivial. It's less efficient than an automatically generated default constructor and prevents noncopyable from being a true POD type.

Even though the copy constructor and copy-assignment operator are hidden from outside code, the member functions and friends of noncopyable can still see and call them. If they're declared but not defined, calling them causes a linker error.

Although this is a commonly accepted idiom, the intent isn't clear unless you understand all of the rules for automatic generation of the special member functions.

In C++11, the noncopyable idiom can be implemented in a way that is more straightforward.

Notice how the problems with the pre-C++11 idiom are resolved:

Generation of the default constructor is still prevented by declaring the copy constructor, but you can bring it back by explicitly defaulting it.

Explicitly defaulted special member functions are still considered trivial, so there's no performance penalty, and noncopyable isn't prevented from being a true POD type.

The copy constructor and copy-assignment operator are public but deleted. It's a compile-time error to define or call a deleted function.

The intent is clear to anyone who understands =default and =delete . You don't have to understand the rules for automatic generation of special member functions.

Similar idioms exist for making user-defined types that are nonmovable, that can only be dynamically allocated, or that can't be dynamically allocated. Each of these idioms have pre-C++11 implementations that suffer similar problems, and that are similarly resolved in C++11 by implementing them in terms of defaulted and deleted special member functions.

Explicitly defaulted functions

You can default any of the special member functions—to explicitly state that the special member function uses the default implementation, to define the special member function with a nonpublic access qualifier, or to reinstate a special member function whose automatic generation was prevented by other circumstances.

You default a special member function by declaring it as in this example:

Notice that you can default a special member function outside the body of a class as long as it's inlinable.

Because of the performance benefits of trivial special member functions, we recommend that you prefer automatically generated special member functions over empty function bodies when you want the default behavior. You can do this either by explicitly defaulting the special member function, or by not declaring it (and also not declaring other special member functions that would prevent it from being automatically generated.)

Deleted functions

You can delete special member functions and normal member functions and nonmember functions to prevent them from being defined or called. Deleting of special member functions provides a cleaner way of preventing the compiler from generating special member functions that you don't want. The function must be deleted as it's declared; it can't be deleted afterwards in the way that a function can be declared and then later defaulted.

Deleting of normal member function or nonmember functions prevents problematic type promotions from causing an unintended function to be called. This works because deleted functions still participate in overload resolution and provide a better match than the function that could be called after the types are promoted. The function call resolves to the more-specific—but deleted—function and causes a compiler error.

Notice in the preceding sample that calling call_with_true_double_only by using a float argument would cause a compiler error, but calling call_with_true_double_only by using an int argument wouldn't; in the int case, the argument will be promoted from int to double and successfully call the double version of the function, even though that might not be what you intend. To ensure that any call to this function by using a non-double argument causes a compiler error, you can declare a template version of the deleted function.

Was this page helpful?

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

C++ Class and Preventing Object Copy

Jan 10, 2015 4 min read #c++ #coding

clonetroopers

A class that represents a wrapper stream of a file should not have its instance copied around. It will cause a confusion in the handling of the actual I/O system. In a similar spirit, if an instance holds a unique private object, copying the pointer does not make sense. A somehow related problem but not necessarily similar is the issue of object slicing .

The following illustration demonstrates a simple class Vehicle that is supposed to have a unique owner, an instance of Person .

For this purpose, the implementation of Person is as simple as:

To show the issue, a helper function info() is implement as follows:

From this example, it is obvious that an instance of Car must not be copied. In particular, another clone of a similar car should not automatically belong to the same owner. In fact, running the subsequent code:

will give the output:

How can we prevent this accidental object copy?

Method 1: Private copy constructor and copy assignment operator

A very common technique is to declare both the copy constructor and copy assignment operator to be private. We do not even need to implement them. The idea is so that any attempt to perform a copy or an assignment will provoke a compile error.

In the above example, Car will be modified to look like the following. Take a look closely at two additional private members of the class.

Now if we try again to assign an instance of Car to a new one, the compiler will complain loudly:

If writing two additional lines containing repetitive names is too cumbersome, a macro could be utilized instead. This is the approach used by WebKit, see its WTF_MAKE_NONCOPYABLE macro from wtf/Noncopyable.h (do not be alarmed, in the context of WebKit source code , WTF here stands for Web Template Framework). Chromium code, as shown in the file base/macros.h , distinguishes between copy constructor and assignment, denoted as DISALLOW_COPY and DISALLOW_ASSIGN macros, respectively.

Method 2: Non-copyable mixin

The idea above can be extended to create a dedicated class which has the sole purpose to prevent object copying. It is often called as Noncopyable and typically used as a mixin . In our example, the Car class can then be derived from this Noncopyable .

Boost users may be already familiar with boost::noncopyable , the Boost flavor of the said mixin. A conceptual, self-contained implementation of that mixin will resemble something like the following:

Our lovely Car class can be written as:

Compared to the first method, using Noncopyable has the benefit of making the intention very clear. A quick glance at the class, right on its first line, and you know right away that its instance is not supposed to be copied.

Method 3: Deleted copy constructor and copy assignment operator

For modern applications, there is less and less reason to get stuck with the above workaround. Thanks to C++11, the solution becomes magically simple: just delete the copy constructor and assignment operator. Our class will look like this instead:

Note that if you use boost::noncopyable mixin with a compiler supporting C++11, the implementation of boost::noncopyable also automatically deletes the said member functions.

With this approach, any accidental copy will result in a quite friendlier error message:

So, which of the above three methods is your favorite?

Related posts:

  • First Look: Kotlin Native
  • Debian on Windows via WSL
  • Windows for Web Development
  • Syntax Highlighting in the Terminal
  • Continuous Tests of Downstream Projects
  • Detecting and Automatically Fixing JavaScript Code Style

♡ this article? Explore more articles and follow me Twitter .

Share this on Twitter Facebook

  • Graphics and multimedia
  • Language Features
  • Unix/Linux programming
  • Source Code
  • Standard Library
  • Tips and Tricks
  • Tools and Libraries
  • Windows API
  • Copy constructors, assignment operators,

Copy constructors, assignment operators, and exception safe assignment

*

How to disable default copy constructor or assignment in C++

📅 2020-Mar-19 ⬩ ✍️ Ashwin Nanjappa ⬩ 🏷️ cpp ⬩ 📚 Archive

There are situations when you would like to disable the default copy constructor and/or default copy assignment operator for many classes or many class hierarchies in your code.

You could delete the default copy constructor or default copy assignment operator for each base class, but that would be onerous and result in lots of duplicated code. Also, the deletion would get hidden among the base class methods.

A cleaner solution: create a class where the default copy constructor and/or default copy assignment operator are deleted. Derive all your classes or the base class of the class hierarchies from this special class. Copy construction and/or copy assignment will now be disabled for all these classes automatically.

Here is an example of such a special class:

Here is an example of deriving from the above class:

Here is the gcc compiler error I got:

Note that this only disables the default copy constructor and/or copy assignment operator. You cannot stop a child class from defining a custom copy constructor and/or copy assignment.

cppreference.com

Move assignment operator.

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.

[ edit ] Syntax

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.

[ edit ] Explanation

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.

[ edit ] Implicitly-declared move assignment operator

If no user-defined move assignment operators are provided for a class type, and all of the following is true:

  • there are no user-declared copy constructors ;
  • there are no user-declared move constructors ;
  • there are no user-declared copy assignment operators ;
  • there is no user-declared destructor ,

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.

[ edit ] Implicitly-defined move assignment operator

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).

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:

[ edit ] Deleted 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:

  • T has a non-static data member of a const-qualified non-class type (or possibly multi-dimensional array thereof).
  • T has a non-static data member of a reference type.
  • T has a potentially constructed subobject of class type M (or possibly multi-dimensional array thereof) such that the overload resolution as applied to find M 's move assignment operator
  • does not result in a usable candidate, or
  • in the case of the subobject being a variant member , selects a non-trivial function.

A deleted implicitly-declared move assignment operator is ignored by overload resolution .

[ edit ] Trivial move assignment operator

The move assignment operator for class T is trivial if all of the following is true:

  • It is not user-provided (meaning, it is implicitly-defined or defaulted);
  • T has no virtual member functions;
  • T has no virtual base classes;
  • the move assignment operator selected for every direct base of T is trivial;
  • the move assignment operator selected for every non-static class type (or array of class type) member of T is trivial.

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.

[ edit ] Eligible move assignment operator

Triviality of eligible move assignment operators determines whether the class is a trivially copyable type .

[ edit ] Notes

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 ] Example

[ edit ] defect reports.

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

[ edit ] See also

  • constructor
  • converting constructor
  • copy assignment
  • copy constructor
  • default constructor
  • aggregate initialization
  • constant initialization
  • copy initialization
  • default initialization
  • direct initialization
  • list initialization
  • reference initialization
  • value initialization
  • zero initialization
  • move constructor
  • 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 11 January 2024, at 20:29.
  • This page has been accessed 783,308 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

C++ – Most concise way to disable copying class in C++11

c c++11 destructor

I have a problem dealing with deprecated since C++11 default generation of copy constructor and copy assignment operator when there is a user-defined destructor.

For most sufficiently simple classes default-generated constructors, operators and destructor are fine. Consider the following reasons to declare destructor:

Making trivial destructor virtual in base class:

Would all 4 copy and move special methods be generated by compiler in these cases? If yes, then I think it is fine and there is no need to complicate Base1 or Base2 .

Printing debug message in destructor:

I believe that in this case copy constructor and assignment operator would be generated; but move constructor and assignment operator would not. I want to avoid using deprecated default-generating and disable copying of D . I also want to avoid flooding D with 4 deleted declarations. Is disabling only one copy constructor enough? Is it a good style?

Best Answer

With C++11, a clean way is to follow the pattern used in boost (see here )

You basically create a base class where copy constructor and copy assignment are deleted, and inherit it:

Related Solutions

C++ – why don’t c++ compilers define operator== and operator=.

The argument that if the compiler can provide a default copy constructor, it should be able to provide a similar default operator==() makes a certain amount of sense. I think that the reason for the decision not to provide a compiler-generated default for this operator can be guessed by what Stroustrup said about the default copy constructor in "The Design and Evolution of C++" (Section 11.4.1 - Control of Copying):

I personally consider it unfortunate that copy operations are defined by default and I prohibit copying of objects of many of my classes. However, C++ inherited its default assignment and copy constructors from C, and they are frequently used.

So instead of "why doesn't C++ have a default operator==() ?", the question should have been "why does C++ have a default assignment and copy constructor?", with the answer being those items were included reluctantly by Stroustrup for backwards compatibility with C (probably the cause of most of C++'s warts, but also probably the primary reason for C++'s popularity).

For my own purposes, in my IDE the snippet I use for new classes contains declarations for a private assignment operator and copy constructor so that when I gen up a new class I get no default assignment and copy operations - I have to explicitly remove the declaration of those operations from the private: section if I want the compiler to be able to generate them for me.

C++ – Rule-of-Three becomes Rule-of-Five with C++11

I'd say the Rule of Three becomes the Rule of Three, Four and Five:

Each class should explicitly define exactly one of the following set of special member functions: None Destructor, copy constructor, copy assignment operator In addition, each class that explicitly defines a destructor may explicitly define a move constructor and/or a move assignment operator. Usually, one of the following sets of special member functions is sensible: None (for many simple classes where the implicitly generated special member functions are correct and fast) Destructor, copy constructor, copy assignment operator (in this case the class will not be movable) Destructor, move constructor, move assignment operator (in this case the class will not be copyable, useful for resource-managing classes where the underlying resource is not copyable) Destructor, copy constructor, copy assignment operator, move constructor (because of copy elision, there is no overhead if the copy assignment operator takes its argument by value) Destructor, copy constructor, copy assignment operator, move constructor, move assignment operator
  • That move constructor and move assignment operator won't be generated for a class that explicitly declares any of the other special member functions (like destructor or copy-constructor or move-assignment operator).
  • That copy constructor and copy assignment operator won't be generated for a class that explicitly declares a move constructor or move assignment operator.
  • And that a class with an explicitly declared destructor and implicitly defined copy constructor or implicitly defined copy assignment operator is considered deprecated.

In particular, the following perfectly valid C++03 polymorphic base class:

Should be rewritten as follows:

A bit annoying, but probably better than the alternative (in this case, automatic generation of special member functions for copying only , without move possibility).

In contrast to the Rule of the Big Three, where failing to adhere to the rule can cause serious damage, not explicitly declaring the move constructor and move assignment operator is generally fine but often suboptimal with respect to efficiency. As mentioned above, move constructor and move assignment operators are only generated if there is no explicitly declared copy constructor, copy assignment operator or destructor. This is not symmetric to the traditional C++03 behavior with respect to auto-generation of copy constructor and copy assignment operator, but is much safer. So the possibility to define move constructors and move assignment operators is very useful and creates new possibilities (purely movable classes), but classes that adhere to the C++03 Rule of the Big Three will still be fine.

For resource-managing classes you can define the copy constructor and copy assignment operator as deleted (which counts as definition) if the underlying resource cannot be copied. Often you still want move constructor and move assignment operator. Copy and move assignment operators will often be implemented using swap , as in C++03. Talking about swap ; if we already have a move-constructor and move-assignment operator, specializing std::swap will become unimportant , because the generic std::swap uses the move-constructor and move-assignment operator if available (and that should be fast enough).

Classes that are not meant for resource management (i.e., no non-empty destructor) or subtype polymorphism (i.e., no virtual destructor) should declare none of the five special member functions; they will all be auto-generated and behave correct and fast.

Related Topic

  • C++ – Easiest way to convert int to string in C++
  • C++ – Implicit member functions of a Class in C++
  • C++ – Call to implicitly deleted copy constructor in LLVM
  • Javascript – How to change the order of a JavaScript object?
  • C++ Data Types
  • C++ Input/Output
  • C++ Pointers
  • C++ Interview Questions
  • C++ Programs
  • C++ Cheatsheet
  • C++ Projects
  • C++ Exception Handling
  • C++ Memory Management

Copy Constructor vs Assignment Operator in C++

  • How to Create Custom Assignment Operator in C++?
  • Assignment Operators In C++
  • Why copy constructor argument should be const in C++?
  • Advanced C++ | Virtual Copy Constructor
  • Move Assignment Operator in C++ 11
  • Self assignment check in assignment operator
  • Is assignment operator inherited?
  • Copy Constructor in C++
  • How to Implement Move Assignment Operator in C++?
  • Default Assignment Operator and References in C++
  • Can a constructor be private in C++ ?
  • When is a Copy Constructor Called in C++?
  • C++ Assignment Operator Overloading
  • std::move in Utility in C++ | Move Semantics, Move Constructors and Move Assignment Operators
  • C++ Interview questions based on constructors/ Destructors.
  • Assignment Operators in C
  • Copy Constructor in Python
  • Copy Constructor in Java
  • Constructors in Objective-C

Copy constructor and Assignment operator are similar as they are both used to initialize one object using another object. But, there are some basic differences between them:

Consider the following C++ program. 

Explanation: Here, t2 = t1;  calls the assignment operator , same as t2.operator=(t1); and   Test t3 = t1;  calls the copy constructor , same as Test t3(t1);

Must Read: When is a Copy Constructor Called in C++?

Please Login to comment...

Similar reads, improve your coding skills with practice.

 alt=

What kind of Experience do you want to share?

IMAGES

  1. [100% Working Code]

    disable copy assignment operator c

  2. Assignment Operators in C

    disable copy assignment operator c

  3. Quick Q: Most concise way to disable copy and move semantics : Standard C++

    disable copy assignment operator c

  4. C programming +=

    disable copy assignment operator c

  5. Assignment Operators in C » PREP INSTA

    disable copy assignment operator c

  6. Assignment Operators in C++

    disable copy assignment operator c

VIDEO

  1. assignment Operator C Language in Telugu

  2. Assignment Operator in C Programming

  3. Augmented assignment operators in C

  4. History copy / assignment first page idea

  5. Assignment Operator in C Programming

  6. 043024 COSC 1337 C++ Class Memory Mgmt: copy assignment

COMMENTS

  1. Most concise way to disable copying class in C++11

    14. Deleting the copy-constructor and copy-assignment operator is the simplest and clearest way to disable copying: class X. {. X(X const &) = delete; void operator=(X const &x) = delete; }; I don't follow what you are talking about with virtual destructors in the question body .

  2. c++

    The alternative is to declare a copy-constructor private and leave it undefined, or define it with a BOOST_STATIC_ASSERT(false). If you are working with C++11 you can also delete your copy constructor: class nocopy. {. nocopy( nocopy const& ) = delete; }; answered Oct 19, 2011 at 15:37. K-ballo.

  3. Copy assignment operator

    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.

  4. Quick Q: Most concise way to disable copy and move semantics

    Most concise way to disable copy and move semantics. According to this chart (by Howard Hinnant): The most concise way is to =delete move assignment operator (or move constructor, but it can cause problems mentioned in comments). Though, in my opinion the most readable way is to =delete both copy constructor and copy assignment operator.

  5. Copy assignment operator

    The copy assignment operator is called whenever selected by overload resolution, e.g. when an object appears on the left side of an assignment expression. Implicitly-declared copy assignment operator If no user-defined copy assignment operators are provided for a class type ( struct , class , or union

  6. Copy assignment operator

    The copy assignment operator selected for every non-static class type (or array of class type) memeber 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.

  7. Preventing Object Copy in C++ (3 Different Ways)

    Using Deleted copy constructor and copy assignment operator: Above two ways are quite complex, C++11 has come up with a simpler solution i.e. just delete the copy constructor and assignment operator. 'Base::Base(const Base&)'. Base b2(b1); // Calls copy constructor. Base(const Base &temp_obj) = delete;

  8. Copy constructors and copy assignment operators (C++)

    Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x);. Use the copy constructor. If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you.

  9. c++

    By making ctor and assignment private (or by declaring them as =delete in C++11) you disable copy. The point here is WHERE you have to do that. To stay with your code, IAbstract is not an issue. (note that doing what you did, you assign the *a1 IAbstract subobject to a2, loosing any reference to Derived. Value assignment is not polymorphic)

  10. Explicitly Defaulted and Deleted Functions

    Benefits of explicitly defaulted and deleted functions. In C++, the compiler automatically generates the default constructor, copy constructor, copy-assignment operator, and destructor for a type if it doesn't declare its own. These functions are known as the special member functions, and they're what make simple user-defined types in C++ ...

  11. The rule of three/five/zero

    Rule of three. If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three. Because C++ copies and copy-assigns objects of user-defined types in various situations (passing/returning by value, manipulating a container, etc), these special ...

  12. Copy elision

    Non-mandatory copy /move (since C++11) elision. Under the following circumstances, the compilers are permitted, but not required to omit the copy and move (since C++11) construction of class objects even if the copy /move (since C++11) constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to.

  13. C++ Class and Preventing Object Copy · ariya.io

    C++ Class and Preventing Object Copy. Jan 10, 2015 4 min read #c++ #coding. In some cases, an instance of a C++ class should not be copied at all. There are three ways to prevent such an object copy: keeping the copy constructor and assignment operator private, using a special non-copyable mixin, or deleting those special member functions.. A class that represents a wrapper stream of a file ...

  14. Copy constructors, assignment operators,

    Note that none of the following constructors, despite the fact that. they could do the same thing as a copy constructor, are copy. constructors: 1. 2. MyClass( MyClass* other ); MyClass( const MyClass* other ); or my personal favorite way to create an infinite loop in C++: MyClass( MyClass other );

  15. How to disable default copy constructor or assignment in C++

    Copy construction and/or copy assignment will now be disabled for all these classes automatically. Here is an example of such a special class: class DelCopy { public: DelCopy() = default; ~DelCopy() = default; DelCopy(const DelCopy&) = delete; DelCopy& operator=(DelCopy&) = delete; }; Here is an example of deriving from the above class:

  16. Move assignment operator

    the move assignment operator selected for every non-static class type (or array of class type) member of T is trivial. 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 ...

  17. C++

    The argument that if the compiler can provide a default copy constructor, it should be able to provide a similar default operator==() makes a certain amount of sense. I think that the reason for the decision not to provide a compiler-generated default for this operator can be guessed by what Stroustrup said about the default copy constructor in "The Design and Evolution of C++" (Section 11.4.1 ...

  18. c++

    Jan 29, 2012 at 20:23. 3. @LihO generally if you disable one you disable the other. If you don't disable the assignment operator, you can do this: MyClass a, b; a = b; and if you don't disable the copy constructor you can do MyClass b; MyClass a(b); So if you don't disable both, you can get around the other one being disabled. - Seth Carnegie.

  19. Copy Constructor vs Assignment Operator in C++

    C++ compiler implicitly provides a copy constructor, if no copy constructor is defined in the class. A bitwise copy gets created, if the Assignment operator is not overloaded. Consider the following C++ program. Explanation: Here, t2 = t1; calls the assignment operator, same as t2.operator= (t1); and Test t3 = t1; calls the copy constructor ...

  20. c++

    Copy constructor (and assignment) should be defined when ever the implicitly generated one violates any class invariant. It should be defined as deleted when it cannot be written in a way that wouldn't have undesirable or surprising behaviour. Probably the simplest example is the class std::unique_ptr. As the name implies, it has unique ...