首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >(隐式声明)不能引用--它是已删除的函数。

(隐式声明)不能引用--它是已删除的函数。
EN

Stack Overflow用户
提问于 2020-04-26 04:49:30
回答 1查看 18.3K关注 0票数 7

使用下面的代码,我将面临一个问题。

ABC.h

代码语言:javascript
运行
复制
namespace abcd
{
    class ABC
    {
    public:
        ABC() = delete;
        ABC(const std::string& filename);
        virtual ~ABC();
        ABC(const ABC&) = delete;
        ABC(ABC&&) = default;
    };
}

XYZ.h

代码语言:javascript
运行
复制
using namespace abcd;

class XYZ
{
public:
    void func();
private:
    ABC obj;
    ABC maskfilename(std::string filename);
};

XYZ.cpp

代码语言:javascript
运行
复制
XYZ::func()
{
    obj = maskfilename("abcd.txt"); //Error
}

abcd::ABC XYZ::maskfilename(string filename)
{
    abcd::ABC ret;
    // blah blah...
    return ret;
}

错误:

"abcd::ABC::operator=(const::ABC &)“(隐式声明)不能引用--它是一个已删除的函数

据我所知,它是move构造函数唯一的类(ABC)。

使用这个的正确方法是什么?我希望在maskfilename()类中保留来自XYZ的返回值,因此可以在XYZ类的其他函数中使用它。

如何解决此错误?

EN

Stack Overflow用户

回答已采纳

发布于 2020-04-26 06:48:00

如果使用Microsoft编译器,则会得到MSVC错误C2280

编译器检测到试图引用已删除的函数。此错误可能是由于调用在源代码中已显式标记为=已删除的的成员函数造成的。此错误还可能由对结构或类的隐式特殊成员函数的调用引起,该结构或类由编译器自动声明并标记为已删除的。有关编译器何时自动生成默认或删除的特殊成员函数的详细信息,请参阅特殊成员函数。

在这种情况下,除了转换构造函数之外,类ABC只有一个move构造函数。由于您声明了一个移动构造函数,编译器隐式删除了复制赋值操作符.您还显式地删除了复制构造函数,即声明了一个复制构造函数,只是一个被删除的构造函数。这将阻止隐式生成移动赋值运算符。所以你才会犯这个错误。这一行试图调用已删除的复制赋值操作符。

代码语言:javascript
运行
复制
obj = maskfilename("abcd.txt"); //Error

您可以阅读更多的这里

  • 如果显式声明任何构造函数,则不会自动生成默认构造函数。
  • 如果显式声明了虚拟析构函数,则不会自动生成默认析构函数。
  • 如果显式声明了移动构造函数或移动赋值运算符,则:
    • 不自动生成复制构造函数。
    • 不自动生成复制赋值操作符。

  • 如果显式声明了复制构造函数、复制赋值运算符、移动构造函数、移动赋值运算符或析构函数,则:。
    • 不自动生成移动构造函数。
    • 不自动生成移动赋值操作符。

此外,C++11标准还指定了以下附加规则:

  • 如果显式声明了副本构造函数或析构函数,则不建议自动生成副本赋值操作符。
  • 如果显式声明了副本赋值运算符或析构函数,则不建议自动生成副本构造函数。

由于您希望您的类是一个只移动类,只需声明一个移动赋值运算符即可。然后,同一行将调用移动赋值操作符,并将maskfilename返回的rvalue移动到obj中。

下面是您的类ABC的重新处理实现

代码语言:javascript
运行
复制
class ABC
{
public:
    ABC() = delete;
    ABC(std::string filename) : mFilename(std::move(filename)) {}
    virtual ~ABC() = default;
    ABC(const ABC&) = delete;
    ABC& operator= (const ABC&) = delete;   //deleted copy-assignment operator
    ABC(ABC&&) = default;
    ABC& operator= (ABC&&) = default;   //added move assignment operator
    std::string GetFilename() const { return mFilename; }

private:
    std::string mFilename;
};

在类XYZ中,由于删除了默认构造函数,所以不能有类型为ABC的成员变量obj。如果需要在XYZ的其他方法中使用这样的对象,则可以使用指向ABC的唯一指针。所以我会这样改变:

XYZ.h:

代码语言:javascript
运行
复制
#include "ABC.h"
#include <memory>

class XYZ
{
public:
    void func();

private:
    std::unique_ptr<ABC> obj;
    std::unique_ptr<ABC> maskfilename(std::string filename);
};

XYZ.cpp:

代码语言:javascript
运行
复制
void XYZ::func()
{
    obj = std::move(maskfilename("abcd.txt"));
}

std::unique_ptr<ABC> XYZ::maskfilename(std::string filename)
{
    std::unique_ptr<ABC> ret = std::make_unique<ABC>(filename);
    // blah blah...
    return ret;
}
票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61435943

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档