The deleted functions feature is introduced into the C++11 standard. In this article, I will explain this feature and provide some examples on how to use it.
C++ has six kinds of special member functions:
•Copy assignment operators
•Move assignment operators
These special member functions are used to create, destroy, initialize, convert, and copy class objects.
Suppose that you haven't defined a certain special member function for a class; when such a special member function is needed, the compiler will implicitly declare a default special member function for this class. For example:
X x2=x1; // Fine. A default copy constructor is implicitly
// defined and called by the compiler.
x3=x1; // Fine. A default copy assignment operator is
// implicitly defined and called by the compiler.
In this example, there is no user-defined copy constructor or copy assignment operator. However, when these two special member functions are needed, the compiler will implicitly declare a default copy constructor and a copy assignment operator.
In some cases, having the compiler define special member functions implicitly can benefit programmers:
•Programmers need not to manually define these special member functions. The manual definition requires more coding effort.
•The compiler implicitly defined member functions are more efficient than the user-defined special member functions.
However, it might become a problem if you want to forbid copy or assignment operations between class objects. but you cannot stop the compiler from defining the default copy constructor or copy assignment operator implicitly.
To address this problem, C++11 introduced the deleted functions feature.
The C++11 standard introduced deleted function declaration as a new form of function declaration.
To declare a deleted function, you can append the “=delete;” specifier to the end of a function declaration. The compiler prohibits the usage of a deleted function. For example, you can declare the implicitly defined copy constructor and copy assignment operator of class X as deleted functions to prevent object copy of that class.
X(const X&) = delete; //deleted copy constructor
X& operator = (const X &) = delete; //deleted copy assignment operator
X x2=x1; //Error. The usage of the copy constructor is disabled.
x3=x1; //Error. The usage of the copy assignment operator is disabled.
In example 2, although only one copy constructor and one copy assignment operator are declared as deleted functions explicitly, the compiler can detect the declarations of the user-defined copy constructor and copy assignment operator. Thus, the compiler will no longer implicitly define any other copy constructors or copy assignment operators that have different parameters. In this case, the copy and assign operations between class objects are totally prohibited.
Compiler Error C2280
- 4 minutes to read
'declaration': attempting to reference a deleted function
The compiler detected an attempt to reference a function. This error can be caused by a call to a member function that has been explicitly marked as in the source code. This error can also be caused by a call to an implicit special member function of a struct or class that is automatically declared and marked as by the compiler. For more information about when the compiler automatically generates or special member functions, see Special member functions.
Example: Explicitly deleted functions
A call to an explicitly function causes this error. An explicitly member function implies that the class or struct is intentionally designed to prevent its use, so to fix this issue, you should change your code to avoid it.
Example: Uninitialized data members
An uninitialized reference type data member or data member causes the compiler to implicitly declare a default constructor. To fix this issue, initialize the data member when it is declared.
Example: Reference and const data members
A or reference type data member causes the compiler to declare a copy assignment operator. Once initialized, these members can't be assigned to, so a simple copy or move can't work. To fix this issue, we recommend you change your logic to remove the assignment operations that cause the error.
Example: Movable deletes implicit copy
If a class declares a move constructor or move assignment operator, but does not explicitly declare a copy constructor, the compiler implicitly declares a copy constructor and defines it as . Similarly, if a class declares a move constructor or move assignment operator, but does not explicitly declare a copy assignment operator, the compiler implicitly declares a copy assignment operator and defines it as . To fix this issue, you must explicitly declare these members.
When you see error C2280 in connection with a , it is almost certainly because you are attempting to invoke its copy constructor, which is a function. By design, a cannot be copied. Use a move constructor to transfer ownership instead.
Example: Variant and volatile members
Versions of the compiler before Visual Studio 2015 Update 2 were non-conforming and generated default constructors and destructors for anonymous unions. These are now implicitly declared as . Those versions also allowed non-conforming implicit definition of copy and move constructors and copy and move assignment operators in classes and structs that have member variables. The compiler now considers these to have non-trivial constructors and assignment operators, and doesn't generate implementations. When such a class is a member of a union, or an anonymous union inside of a class, the copy and move constructors and copy and move assignment operators of the union or class are implicitly defined as . To fix this issue, you must explicitly declare the required special member functions.
Example: Indirect base members deleted
Versions of the compiler before Visual Studio 2015 Update 2 were non-conforming and allowed a derived class to call special member functions of indirectly-derived base classes. The compiler now issues compiler error C2280 when such a call is made.
In this example, class indirectly derives from private virtual . In conforming code, this makes the members of inaccessible to ; an object of type can't be default constructed or destroyed. To fix this issue in code that relied on the old compiler behavior, change the intermediate class to use derivation, or change the class to use direct derivation: