gpt4 book ai didi

c++ - 'empty' 构造函数或析构函数会做与生成的相同的事情吗?

转载 作者:IT老高 更新时间:2023-10-28 12:07:38 26 4
gpt4 key购买 nike

假设我们有一个(玩具)C++ 类,如下所示:

class Foo {
public:
Foo();
private:
int t;
};

由于没有定义析构函数,C++ 编译器应该自动为类 Foo 创建一个析构函数。 .如果析构函数不需要清理任何动态分配的内存(也就是说,我们可以合理地依赖编译器给我们的析构函数),则将定义一个空的析构函数,即。
Foo::~Foo() { }

和编译器生成的一样吗?一个空的构造函数呢——也就是 Foo::Foo() { } ?

如果存在差异,它们存在于何处?如果不是,一种方法是否优于另一种方法?

最佳答案

它会做同样的事情(本质上什么都没有)。但这和没有写不一样。因为编写析构函数将需要一个工作的基类析构函数。如果基类析构函数是私有(private)的,或者有任何其他原因无法调用它,那么你的程序就有问题。考虑这个

struct A { private: ~A(); };
struct B : A { };

没关系,只要您不需要销毁 B 类型的对象(因此,隐式为 A 类型)-就像您从不对动态创建的对象调用 delete 一样,或者您从不在其中创建它的对象第一名。如果这样做,编译器将显示适当的诊断信息。现在,如果您明确提供一个
struct A { private: ~A(); };
struct B : A { ~B() { /* ... */ } };

那将尝试隐式调用基类的析构函数,并且会在 ~B 的定义时间导致诊断。 .

还有一个区别集中在析构函数的定义和对成员析构函数的隐式调用上。考虑这个智能指针成员
struct C;
struct A {
auto_ptr<C> a;
A();
};

让我们假设类型为 C 的对象在 .cpp 中 A 的构造函数的定义中创建文件,其中还包含 struct C 的定义.现在,如果你使用 struct A ,并要求销毁 A对象,编译器将提供析构函数的隐式定义,就像上面的例子一样。该析构函数还将隐式调用 auto_ptr 对象的析构函数。这将删除它持有的指针,指向 C对象 - 不知道 C 的定义!出现在 .cpp定义结构 A 的构造函数的文件。

这实际上是实现 pimpl 成语的常见问题。这里的解决方案是添加一个析构函数并在 .cpp 中提供它的空定义。文件,其中结构 C被定义为。当它调用其成员的析构函数时,它就会知道 struct C 的定义。 , 并且可以正确调用它的析构函数。
struct C;
struct A {
auto_ptr<C> a;
A();
~A(); // defined as ~A() { } in .cpp file, too
};

请注意 boost::shared_ptr没有这个问题:当它的构造函数以某些方式被调用时,它需要一个完整的类型。

另一个在当前 C++ 中有所不同的地方是当你想使用 memset 时。和这样的对象上的 friend ,该对象具有用户声明的析构函数。这些类型不再是 POD(纯旧数据),并且不允许进行位复制。请注意,这个限制并不是真正需要的 - 下一个 C++ 版本已经改善了这种情况,因此只要不进行其他更重要的更改,它仍然允许您对此类类型进行位复制。

既然你要求构造函数:嗯,对于这些事情来说,事情都是一样的。请注意,构造函数还包含对析构函数的隐式调用。在 auto_ptr 之类的东西上,这些调用(即使实际上没有在运行时完成 - 纯粹的可能性在这里已经很重要)将造成与析构函数相同的危害,并且在构造函数中的某些内容抛出时发生 - 然后需要编译器调用析构函数的成员。 This answer使用默认构造函数的隐式定义。

此外,我在上面所说的关于析构函数的可见性和 POD 性也是如此。

关于初始化有一个重要区别。如果您放置了一个用户声明的构造函数,您的类型将不再接收成员的值初始化,并且由您的构造函数进行任何需要的初始化。例子:
struct A {
int a;
};

struct B {
int b;
B() { }
};

在这种情况下,以下总是正确的
assert(A().a == 0);

虽然以下是未定义的行为,因为 b从未初始化(您的构造函数省略了它)。该值可能为零,但也可能是任何其他奇怪的值。试图从这样一个未初始化的对象中读取会导致未定义的行为。
assert(B().b == 0);

new 中使用此语法也是如此。 , 喜欢 new A() (注意末尾的括号 - 如果省略它们,则不会进行值初始化,并且由于没有用户声明的构造函数可以对其进行初始化, a 将保持未初始化状态)。

关于c++ - 'empty' 构造函数或析构函数会做与生成的相同的事情吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1025313/

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