Edit

Share via


Compiler Error C2280

'declaration': attempting to reference a deleted function

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.

Example: Explicitly deleted functions

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.

// C2280_explicit.cpp
// compile with: cl /c /W4 C2280_explicit.cpp
struct A {
    A();
    A(int) = delete;
};

struct B {
    A a1;
    A a2 = A(3); // C2280, calls deleted A::A(int)
    // To fix, remove the call to A(int)
};

void f() {
    B b;    // calls implicit B::B(void)
}

Example: Uninitialized data members

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.

// C2280_uninit.cpp
// compile with: cl /c C2280_uninit.cpp
struct A {
    const int i; // uninitialized const-qualified data
    // members or reference type data members cause
    // the implicit default constructor to be deleted.
    // To fix, initialize the value in the declaration:
    // const int i = 42;
} a;    // C2280

Example: Reference and const data members

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

// C2280_ref.cpp
// compile with: cl /c C2280_ref.cpp
extern int k;
struct A {
    A();
    int& ri = k; // a const or reference data member causes
    // implicit copy assignment operator to be deleted.
};

void f() {
    A a1, a2;
    // To fix, consider removing this assignment.
    a2 = a1;    // C2280
}

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

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.

// C2280_move.cpp
// compile with: cl /c C2280_move.cpp
class base
{
public:
    base();
    ~base();
    base(base&&);
    // Move constructor causes copy constructor to be
    // implicitly declared as deleted. To fix this
    // issue, you can explicitly declare a copy constructor:
    // base(base&);
    // If you want the compiler default version, do this:
    // base(base&) = default;
};

void copy(base *p)
{
    base b{*p};  // C2280
}

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

// C2280_variant.cpp
// compile with: cl /c C2280_variant.cpp
struct A {
    A() = default;
    A(const A&);
};

struct B {
    union {
        A a;
        int i;
    };
    // To fix this issue, declare the required
    // special member functions:
    // B();
    // B(const B& b);
};

int main() {
    B b1;
    B b2(b1);  // C2280
}

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 private virtual base classes. The compiler now issues compiler error C2280 when such a call is made.

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:

// C2280_indirect.cpp
// compile with: cl /c C2280_indirect.cpp
class base
{
protected:
    base();
    ~base();
};

class middle : private virtual base {};
// Possible fix: Replace line above with:
// class middle : protected virtual base {};
class top : public virtual middle {};    // C4594, C4624
// Another possible fix: use direct derivation:
// class top : public virtual middle, private virtual base {};

void destroy(top *p)
{
    delete p;  // C2280
}