【发布时间】:2018-03-03 03:33:00
【问题描述】:
我在 cppreference.com 上找到了这段代码。这是我见过的最奇怪的 C++,对此我有几个问题:
union S
{
std::string str;
std::vector<int> vec;
~S() {}
};
int main()
{
S s = { "Hello, world" };
// at this point, reading from s.vec is undefined behavior
std::cout << "s.str = " << s.str << '\n';
s.str.~basic_string<char>();
new (&s.vec) std::vector<int>;
// now, s.vec is the active member of the union
s.vec.push_back(10);
std::cout << s.vec.size() << '\n';
s.vec.~vector<int>();
}
我想确保我做对了一些事情。
- 联合强制您通过删除默认构造函数来初始化联合成员之一,在这种情况下,他使用 Hello World 初始化了字符串。
- 在他初始化字符串之后,从技术上讲,向量还不存在?我可以访问它,但它尚未构建?
- 他通过调用其析构函数显式销毁字符串对象。在这种情况下,当 S 超出范围时,会调用 ~S() 析构函数吗?如果有,在哪个物体上?如果他没有在字符串上显式调用析构函数是内存泄漏吗?我倾向于不,因为字符串会自行清理,但对于我不知道的工会。他自己调用了字符串和向量的析构函数,所以 ~S() 析构函数似乎没用,但是当我删除它时,我的编译器不会让我编译它。
- 这是我第一次看到有人使用 new 运算符将对象放在堆栈上。在这种情况下,这是唯一可以使用向量的方法吗?
- 当您像他对向量一样使用placement new 时,您不应该对其调用delete,因为尚未分配新内存。通常如果你将 new 放在堆上,你必须 free() 内存以避免泄漏,但在这种情况下,如果他让向量和联合超出范围而不调用析构函数会发生什么?
我觉得这真的很混乱。
【问题讨论】:
-
得说...以前从未见过带有析构函数的
union。好,坏,我不知道。只是没见过。 -
在实践中,您的班级应该知道它使用哪个工会成员,例如成为tagged union;见std::variant;阅读所有union reference 页面,尤其是最后一个标记的联合示例
-
每个帖子一个问题。而且您需要阅读good c++ book 而不是随机询问互联网人
-
@passerby 这一切都如此紧密地结合在一起,几乎是从不同方面看待一个问题。
-
(2) 访问联合的非活动成员是未定义的行为。当前活动成员是写入的联合的最后一个成员。
标签: c++ class destructor unions