不销毁作为联合成员的 class 类型的对象是否安全?
Is it safe not to destroy an object of a class type that is a member of a union?
我有这个例子:
struct A{
A(){std::cout << "A's def-ctor\n";}
~A(){std::cout << "A's dtor\n";}
A(A const&){std::cout << "A's copy-ctor\n";}
A& operator = (A const&){std::cout << "A's copy-assign op\n"; return *this; }
};
struct Foo{
Foo() : curMem_(INT), i_(0){}
~Foo(){
if(curMem_ == CLS_A) // If I comment out this line then what happens?
a_.~A();
}
enum {INT, CHAR, CLS_A, BOOL} curMem_;
union{
int i_;
char c_;
A a_;
bool b_;
};
};
Foo f;
f.curMem_ = Foo::CLS_A;
f.a_ = A();
f.curMem_ = Foo::BOOL;
f.b_ = true;
我们知道 class 默认析构函数不知道联合类型的 class 成员中的哪个成员是活动的,这就是为什么我们确实需要定义析构函数的输出版本。所以union的class类型的成员数据不会自动销毁。那么如果我不显式地调用联合体中那些 class 类型成员的析构函数会发生什么?
如果我注释 Foo
析构函数中的行或删除析构函数本身会发生什么?这是未定义的行为吗?
我的 class A
不通过原始指针管理资源那么为什么当它的对象的成员是一个 union
?谢谢!
P.S:我从 C++ primer 5th edition Chapter 19.6 unions:
Our destructor checks whether the object being destroyed holds a string. If so, the destructor explicitly calls the string destructor (§ 19.1.2, p. 824) to free the memory used by that string. The destructor has no work to do if the union holds a member of any of the built-in types.
“如果联合拥有任何内置类型的成员,则析构函数无事可做。”我认为他可以添加:“或者 class 类型,这取决于琐碎的析构函数”。你怎么看?
[basic.life]p6
中给出的标准的准确写法是:
For an object of a class type, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression ([expr.delete]) is not used to release the storage, the destructor is not implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.
(强调我的)
“取决于副作用”似乎很模糊,并且有很多关于堆栈溢出的问题讨论这个措辞。你的 A
class 的析构函数似乎有调用 I/O 函数的副作用,所以你 运行 似乎陷入了未定义的行为。
即使它不是 UB,如果它是 std::vector
、std::string
或 std::fstream
,您也会泄漏内存或文件句柄等资源。这完全取决于 class 的析构函数(以及 class 的任何成员)的作用。
因为“我的 class A
不通过原始指针管理资源”,它应该有一个简单的析构函数。在这种情况下,这一点没有实际意义,不调用析构函数就可以了。
我有这个例子:
struct A{
A(){std::cout << "A's def-ctor\n";}
~A(){std::cout << "A's dtor\n";}
A(A const&){std::cout << "A's copy-ctor\n";}
A& operator = (A const&){std::cout << "A's copy-assign op\n"; return *this; }
};
struct Foo{
Foo() : curMem_(INT), i_(0){}
~Foo(){
if(curMem_ == CLS_A) // If I comment out this line then what happens?
a_.~A();
}
enum {INT, CHAR, CLS_A, BOOL} curMem_;
union{
int i_;
char c_;
A a_;
bool b_;
};
};
Foo f;
f.curMem_ = Foo::CLS_A;
f.a_ = A();
f.curMem_ = Foo::BOOL;
f.b_ = true;
我们知道 class 默认析构函数不知道联合类型的 class 成员中的哪个成员是活动的,这就是为什么我们确实需要定义析构函数的输出版本。所以union的class类型的成员数据不会自动销毁。那么如果我不显式地调用联合体中那些 class 类型成员的析构函数会发生什么?
如果我注释
Foo
析构函数中的行或删除析构函数本身会发生什么?这是未定义的行为吗?我的 class
A
不通过原始指针管理资源那么为什么当它的对象的成员是一个union
?谢谢!
P.S:我从 C++ primer 5th edition Chapter 19.6 unions:
Our destructor checks whether the object being destroyed holds a string. If so, the destructor explicitly calls the string destructor (§ 19.1.2, p. 824) to free the memory used by that string. The destructor has no work to do if the union holds a member of any of the built-in types.
“如果联合拥有任何内置类型的成员,则析构函数无事可做。”我认为他可以添加:“或者 class 类型,这取决于琐碎的析构函数”。你怎么看?
[basic.life]p6
中给出的标准的准确写法是:
For an object of a class type, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression ([expr.delete]) is not used to release the storage, the destructor is not implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.
(强调我的)
“取决于副作用”似乎很模糊,并且有很多关于堆栈溢出的问题讨论这个措辞。你的 A
class 的析构函数似乎有调用 I/O 函数的副作用,所以你 运行 似乎陷入了未定义的行为。
即使它不是 UB,如果它是 std::vector
、std::string
或 std::fstream
,您也会泄漏内存或文件句柄等资源。这完全取决于 class 的析构函数(以及 class 的任何成员)的作用。
因为“我的 class A
不通过原始指针管理资源”,它应该有一个简单的析构函数。在这种情况下,这一点没有实际意义,不调用析构函数就可以了。