我遇到过一种情况,其中类型安全的c ++会生成不匹配的ctor / dtor。以下代码为A生成两个构造函数。默认构造函数也构造其基数(B),但是默认生成的复制/移动ctor不会构造B。后来,它破坏了B,因此我们得到了不匹配的ctor / dtor。
我已经用gcc和clang尝试过了,但都失败了。在gcc错误报告论坛中,他们建议这不是gcc问题。我可能会遗漏一些东西,但是当类型安全代码导致对尚未构造的类的dtor调用时,这不是很奇怪吗?
B() -> INSERT: 0x7fff55398b2f
~B() -> ERASE: 0x7fff55398b2f
~B() -> ERASE: 0x7fff55398b40 // <- unmatched dtor call
Assertion failed: (!all.empty()), function ~B, file gcc_bug.c, line 20.
代码如下:
#include <set>
#include <iostream>
#include <cstdint>
#include <cassert>
#include <experimental/optional>
std::set<std::uintptr_t> all;
struct B
{
B()
{
std::cerr << "B() -> INSERT: " << this << "\n";
all.insert((std::uintptr_t)this);
}
~B()
{
std::cerr << "~B() -> ERASE: " << this << "\n";
assert(!all.empty()); // FAILS
assert(all.find((std::uintptr_t)this) != all.end()); // FAILS
all.erase((std::uintptr_t)this);
}
};
struct A : B {};
static std::experimental::optional<A> f()
{
A a;
return a;
}
int main()
{
auto a = f();
return 0;
}
您有一个B
由隐式定义的副本构造函数创建的对象。当然,这不是在打电话B::B()
。如果添加以下构造函数:
B(const B& other) : B()
{
*this = other;
}
您将看到输出:
B() -> INSERT: 0x7ffe57ef918f
B() -> INSERT: 0x7ffe57ef91b0
~B() -> ERASE: 0x7ffe57ef918f
~B() -> ERASE: 0x7ffe57ef91b0
要带走的重要一点是:每个构造函数都完全构造对象。默认情况下,复制构造函数不会调用默认构造函数(显然,反之亦然)。因此,如果您需要在每个构造函数中执行某些操作,则必须在每个构造函数中通过直接调用或构造函数链接来明确地执行该操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句