【问题标题】:How to fix 'attempting to reference a deleted function' when the compiler implicitly deleted it当编译器隐式删除它时如何修复“尝试引用已删除的函数”
【发布时间】:2019-09-09 08:20:03
【问题描述】:

我正在尝试创建一个通用类,它可以以最基本的形式表示任何对象,位。为此,我创建了一个由字符数组(本质上是字节)和字符组成的对象组成的 Union。不幸的是,在构建时,我的工会收到了一个奇怪的警告和错误。

警告:“析构函数被隐式定义为已删除。”

错误:“正在尝试引用已删除的函数。”

(都出现在我的联合定义之后的行)

我知道您可以为结构、类和联合创建自定义析构函数,但如果您不释放动态内存,则不需要,对吗?然而不知何故,我从未定义过的析构函数被自动调用,编译器隐式删除了它。因此出现错误。

接下来我尝试在联合中定义析构函数;它什么也没做,因为我从来没有向操作系统索要额外的内存。它再次被删除。我需要弄清楚为什么编译器会删除我的函数,然后在删除它后尝试调用它时导致错误。

我尝试在 Microsoft Visual Studio 列表中查找此错误,结果发现不公开构造函数会导致此错误。此外,在这里在线查看时,我发现复制构造函数通常会导致错误,因为它从未定义过。所以我通过创建自己的类并使用复制构造函数 = 对其进行了测试。它工作得很好,但是在尝试将它与我的 typeAsChar 类一起使用时给了我同样的错误。有趣的是,当我将我的类与 C 默认结构、int、double 等一起使用时,不会调用此错误。

这是导致问题的代码。

template <class type>
union typeAsChar
{
    type obj;
    char arr[sizeof(type)];
};

template <class type> 
class wontWork
{
public:

    wontWork() {/* Do nothing, no data entered */}
    wontWork(const type& obj) { foo.obj = obj; }
    ~wontWork() {/* When this goes out of scope, the default
                     destructor of the member 'type' should be called */}

    typeAsChar<type> foo;
};

int main()
{
    double testNum = 12345;
    std::string testStr = "Hello World\n";

    wontWork<std::string> test1(testStr); // has error
    std::cout << test1.foo.obj;

    wontWork<double> test2(testNum); // No error
    std::cout << test2.foo.obj;

        return 0;
}

奇怪的是,在 wontWork&lt;std::string&gt; 被注释掉的情况下,它可以完美地编译和运行,但是当我的类是使用标准 c 结构(int、double 等)以外的任何对象创建时会失败。任何关于此事的澄清将不胜感激。

【问题讨论】:

  • unions 并不是真正的 C++ 兼容。它们实际上是 C 的保留。在 C++ 中,您应该使用 std::variant 而不是联合,以避免这个问题。
  • 我会试试的
  • 感谢您的建议,但变体对我不起作用,因为我需要将一个特定类型的对象传递给它,然后是一个字符数组(理想情况下与传入的第一种类型)。我可以传入数组的唯一方法是通过指向 char 的指针,但我不想传入并修改指针。相反,我希望修改它指向的字符数组。
  • 好吧,对于初学者来说,无论是通过联合还是变体,您实际上都无法将“字符数组”转换为 C++ std::string。 C++ 不能以这种方式工作。您会惊讶地发现sizeof(std::string) 是一个非常小的值,并且无论字符串为空还是包含“战争与和平”的整个文本,它的大小始终相同。那么,鉴于此,您希望如何实现您的目标?抱歉,但 C++ 根本无法以这种方式工作。
  • 通过字符数组。字面上地。 char arr[50 /*在这里选择一个随机数 */].本质上是一个 c 字符串,而不是 std::string

标签: c++ templates destructor implicit


【解决方案1】:

这是@Miles Budnek 的完美答案。非常感谢您提供的信息,我从不知道这是 c++ 中的功能。

"reinterpret_cast(&object) 是一种定义明确的方式来访问构成对象的字节(即使它对于 std::string 之类的东西不是很有用)。通过联合进行类型双关的定义不明确。 ——迈尔斯·布德内克”

【讨论】:

  • 您可能想了解 POD(普通旧数据)。由这些组成的对象是自包含的,这对您的方法至关重要。 stackoverflow.com/questions/146452/what-are-pod-types-in-c
  • 我刚做了。很高兴知道访问工会的另一个成员而不是您分配的成员是未定义的行为。现在我觉得很奇怪,我的教授通过分配一个整数并将其表示为一个字符数组来向我介绍联合。根据 c++,这实际上是未定义的行为,不应使用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
  • 2015-02-14
  • 2023-04-01
相关资源
最近更新 更多