gpt4 book ai didi

c++ - 如果 operator delete 没有实现,为什么这不能编译

转载 作者:搜寻专家 更新时间:2023-10-31 02:23:53 25 4
gpt4 key购买 nike

如果 operator delete 没有实现,为什么不能编译?


class A
{
public:
virtual ~A(){ }
private:
void operator delete(void *p);
};

int main()
{
A a;
}

用g++编译,报错如下:

对“A::operator delete(void*)”的 undefined reference

如果给它一个空的操作符删除实现

class A
{
public:
virtual ~A(){ }
private:
void operator delete(void *p) {}
};

int main()
{
A a;
}

或删除“虚拟”

class A
{
public:
~A(){ }
private:
void operator delete(void *p);
};

int main()
{
A a;
}

都编译成功。

这个怎么解释?

最佳答案

嗯,两者之间有很大的区别:

void operator delete(void *p); 

void operator delete(void *p) {}

前者只是声明函数;后者定义它。当你声明一个函数时,你基本上只是在说“有一个函数,这里是它的参数类型和它的返回值”,但是当你定义一个函数时,你是在写下实际包含该函数的代码.用一对空大括号定义的函数什么都不做;声明但未定义的函数可能会做任何事情(直到看到定义才能知道)。显然,除非定义了函数,否则无法调用它。不太明显的是,除非定义了函数,否则无法获取其地址。显然,这两个语句都暗示,如果您调用一个函数或获取函数的地址,而您没有定义它,那么您的程序就是病式的。

通常,未能定义需要定义的内容的结果是链接器错误。那是因为当您以需要定义的方式使用某些东西时,编译器会创建一个符号,告诉链接器一旦找到定义就将地址插入所需的位置。如果链接器找不到定义(以及地址),那么它就无法完成它的工作。

C++ 标准有一套神秘的规则,基本上告诉您在什么条件下需要定义一个函数。有时会,有时不会。一个简单的例子:

int f();
int main() {}

这很好;函数 f 永远不会被调用,无论是隐式的还是显式的;它的地址永远不会被占用;它甚至没有被调用的机会。因此,即使未定义 f,该程序也会编译。

根据标准,如果odr-used 必须定义一个函数。该标准对 operator delete ([basic.def.odr]/3) 有以下说明:

... A non-placement allocation or deallocation function for a class is odr-used by the definition of a constructor of that class. A non-placement deallocation function for a class is odr-used by the definition of the destructor of that class, or by being selected by the lookup at the point of definition of a virtual destructor (12.4). (footnote 26)...

因此:如果您的类定义了构造函数或析构函数,它会使用您的 operator delete。因此,您的析构函数是否为虚函数并不重要;如果没有operator delete 的定义,您的程序格式错误,因为您定义了一个析构函数。 [1]

现在,您可能会问为什么您的编译器和链接器在析构函数为非虚函数时不报错。好吧,工具链有时会接受代码,即使它们应该拒绝它。在这种特殊情况下,如果析构函数不是虚拟的,那么您的程序实际上不需要 operator delete 的地址,因此即使您从未定义它,链接器也不会提示。但是当你使析构函数成为虚拟时,因为释放函数的查找是基于被释放对象的动态类型,所以需要有一个释放函数的 vtable 条目,这意味着它的地址必须是已知的。因此链接错误。 (再次重申,即使您的编译器和链接器在析构函数为非虚拟时接受代码,但根据我对标准的阅读,它仍然是格式错误的代码。)

[1] 注意,只要你真正创建了一个A类型的对象,就不可能没有构造函数和析构函数的定义,即使你没有定义它们你自己;也就是说,编译器将隐式生成定义。)

关于c++ - 如果 operator delete 没有实现,为什么这不能编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28779819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com