|
| 1 | +--- |
| 2 | +title: "Compiler Error C2280 | Microsoft Docs" |
| 3 | +ms.custom: "" |
| 4 | +ms.date: "04/25/2017" |
| 5 | +ms.reviewer: "" |
| 6 | +ms.suite: "" |
| 7 | +ms.technology: |
| 8 | + - "devlang-cpp" |
| 9 | +ms.tgt_pltfrm: "" |
| 10 | +ms.topic: "article" |
| 11 | +f1_keywords: |
| 12 | + - "C2280" |
| 13 | +helpviewer_keywords: |
| 14 | + - "C2280" |
| 15 | +dev_langs: |
| 16 | + - "C++" |
| 17 | +ms.assetid: e6c5b1fb-2b9b-4554-8ff9-775eeb37161b |
| 18 | +caps.latest.revision: 8 |
| 19 | +author: "corob-msft" |
| 20 | +ms.author: "corob" |
| 21 | +manager: "ghogen" |
| 22 | +translation.priority.ht: |
| 23 | + - "de-de" |
| 24 | + - "es-es" |
| 25 | + - "fr-fr" |
| 26 | + - "it-it" |
| 27 | + - "ja-jp" |
| 28 | + - "ko-kr" |
| 29 | + - "ru-ru" |
| 30 | + - "zh-cn" |
| 31 | + - "zh-tw" |
| 32 | +translation.priority.mt: |
| 33 | + - "cs-cz" |
| 34 | + - "pl-pl" |
| 35 | + - "pt-br" |
| 36 | + - "tr-tr" |
| 37 | +--- |
| 38 | +# Compiler Error C2280 |
| 39 | + |
| 40 | +'*declaration*': attempting to reference a deleted function |
| 41 | + |
| 42 | +The compiler detected an attempt to reference a `deleted` function. This error can be caused by a call to a member function that has been explicitly marked as `= deleted` 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 `deleted` by the compiler. For more information about when the compiler automatically generates `default` or `deleted` special member functions, see [Special member functions](../../cpp/special-member-functions.md). |
| 43 | + |
| 44 | +## Example: Explicitly deleted functions |
| 45 | + |
| 46 | +A call to an explicitly `deleted` function causes this error. An explicitly `deleted` 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. |
| 47 | + |
| 48 | +```cpp |
| 49 | +// C2280_explicit.cpp |
| 50 | +// compile with: cl /c /W4 C2280_explicit.cpp |
| 51 | +struct A { |
| 52 | + A(); |
| 53 | + A(int) = delete; |
| 54 | +}; |
| 55 | + |
| 56 | +struct B { |
| 57 | + A a1; |
| 58 | + A a2 = A(3); // C2280, calls deleted A::A(int) |
| 59 | + // To fix, remove the call to A(int) |
| 60 | +}; |
| 61 | + |
| 62 | +void f() { |
| 63 | + B b; // calls implicit B::B(void) |
| 64 | +} |
| 65 | +``` |
| 66 | + |
| 67 | +## Example: Uninitialized data members |
| 68 | + |
| 69 | +An uninitialized reference type data member or `const` data member causes the compiler to implicitly declare a `deleted` default constructor. To fix this issue, initialize the data member when it is declared. |
| 70 | + |
| 71 | +```cpp |
| 72 | +// C2280_uninit.cpp |
| 73 | +// compile with: cl /c C2280_uninit.cpp |
| 74 | +struct A { |
| 75 | + const int i; // uninitialized const-qualified data |
| 76 | + // members or reference type data members cause |
| 77 | + // the implicit default constructor to be deleted. |
| 78 | + // To fix, initialize the value in the declaration: |
| 79 | + // const int i = 42; |
| 80 | +} a; // C2280 |
| 81 | +``` |
| 82 | + |
| 83 | +## Example: Reference and const data members |
| 84 | + |
| 85 | +A `const` or reference type data member causes the compiler to declare a `deleted` copy assignment operator. Once initialized, these members can't be assigned to. To fix this issue, we recommend you change your logic to remove the assignment operations that cause the error. |
| 86 | + |
| 87 | +```cpp |
| 88 | +// C2280_ref.cpp |
| 89 | +// compile with: cl /c C2280_ref.cpp |
| 90 | +extern int k; |
| 91 | +struct A { |
| 92 | + A(); |
| 93 | + int& ri = k; // a const or reference data member causes |
| 94 | + // implicit copy assignment operator to be deleted. |
| 95 | +}; |
| 96 | + |
| 97 | +void f() { |
| 98 | + A a1, a2; |
| 99 | + // To fix, consider removing this assignment. |
| 100 | + a2 = a1; // C2280 |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +## Example: Movable deletes implicit copy |
| 105 | + |
| 106 | +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 `deleted`. 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 `deleted`. To fix this issue, you must explicitly declare these members. |
| 107 | + |
| 108 | +When you see error C2280 in connection with a `unique_ptr`, it is almost certainly because you are attempting to invoke its copy constructor, which is a `deleted` function. By design, a `unique_ptr` cannot be copied. Use a move constructor to transfer ownership instead. |
| 109 | +
|
| 110 | +```cpp |
| 111 | +// C2280_move.cpp |
| 112 | +// compile with: cl /c C2280_move.cpp |
| 113 | +class base |
| 114 | +{ |
| 115 | +public: |
| 116 | + base(); |
| 117 | + ~base(); |
| 118 | + base(base&&); |
| 119 | + // Move constructor causes copy constructor to be |
| 120 | + // implicitly declared as deleted. To fix this |
| 121 | + // issue, you can explicitly declare a copy constructor: |
| 122 | + // base(base&); |
| 123 | + // If you want the compiler default version, do this: |
| 124 | + // base(base&) = default; |
| 125 | +}; |
| 126 | +
|
| 127 | +void copy(base *p) |
| 128 | +{ |
| 129 | + base b{*p}; // C2280 |
| 130 | +} |
| 131 | +``` |
| 132 | + |
| 133 | +## Example: Variant and volatile members |
| 134 | + |
| 135 | +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 `deleted`. Those versions also allowed non-conforming implicit definition of `default` copy and move constructors and `default` copy and move assignment operators in classes and structs that have `volatile` member variables. The compiler now considers these to have non-trivial constructors and assignment operators, and doesn't generate `default` 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 `deleted`. To fix this issue, you must explicitly declare the required special member functions. |
| 136 | + |
| 137 | +```cpp |
| 138 | +// C2280_variant.cpp |
| 139 | +// compile with: cl /c C2280_variant.cpp |
| 140 | +struct A { |
| 141 | + A() = default; |
| 142 | + A(const A&); |
| 143 | +}; |
| 144 | + |
| 145 | +struct B { |
| 146 | + union { |
| 147 | + A a; |
| 148 | + int i; |
| 149 | + }; |
| 150 | + // To fix this issue, declare the required |
| 151 | + // special member functions: |
| 152 | + // B(); |
| 153 | + // B(const B& b); |
| 154 | +}; |
| 155 | + |
| 156 | +int main() { |
| 157 | + B b1; |
| 158 | + B b2(b1); // C2280 |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +## Example: Indirect base members deleted |
| 163 | + |
| 164 | +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 `private virtual` base classes. The compiler now issues compiler error C2280 when such a call is made. |
| 165 | + |
| 166 | +In this example, class `top` indirectly derives from private virtual `base`. In conforming code, this makes the members of `base` inaccessible to `top`; an object of type `top` 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 `protected virtual` derivation, or change the `top` class to use direct derivation: |
| 167 | +
|
| 168 | +```cpp |
| 169 | +// C2280_indirect.cpp |
| 170 | +// compile with: cl /c C2280_indirect.cpp |
| 171 | +class base |
| 172 | +{ |
| 173 | +protected: |
| 174 | + base(); |
| 175 | + ~base(); |
| 176 | +}; |
| 177 | +
|
| 178 | +class middle : private virtual base {}; |
| 179 | +// Possible fix: Replace line above with: |
| 180 | +// class middle : protected virtual base {}; |
| 181 | +class top : public virtual middle {}; // C4594, C4624 |
| 182 | +// Another possible fix: use direct derivation: |
| 183 | +// class top : public virtual middle, private virtual base {}; |
| 184 | +
|
| 185 | +void destroy(top *p) |
| 186 | +{ |
| 187 | + delete p; // C2280 |
| 188 | +} |
| 189 | +``` |
| 190 | + |
0 commit comments