物体的破坏是否正确发生?
Is the destruction of the objects properly happend?
我在这里阅读了这篇文章:何时使用虚拟析构函数? 我的想法是,每当我们使用new
或智能指针动态创建对象时,基类都应该有一个适当的virtual
析构函数,用于在删除时销毁对象。
然后我找到了一些如下代码(简化形式(,它错过了Base
中的virtual
析构函数:
class Base
{
public:
// some static members
};
class Derived1 final : public Base
{
public:
// other members
// default constructor does not construct the `Base` in constructor member intilizer
Derived1() {};
virtual ~Derived1() = default;
};
class Derived2 final : public Base
{
public:
// other members
Derived2() {}; // default constructor does not construct the `Base`
~Derived2() = default;
};
int main()
{
// creating Derived1 dynamically // 1
Derived1 *d1Object = new Derived1{};
// creating Derived2 dynamically // 2
Derived2 *d2Object1 = new Derived2{};
// creating Derived2 statically // 3
Derived2 d2Object2{};
// clean up
delete d1Object;
delete d2Object1;
}
我的问题是:
- 我在任何一种情况下(
1, 2, 3
(是否有未定义的行为?为什么?
在 - 两个派生类的构造函数的成员初始值设定项列表中构造
Base
不是必需的(在上述特定情况下(?
我正在使用 C++11。
该代码中的对象指针实际上不是多态的:*d1Object
的静态类型与其动态类型相同,即Derived1&
(其他对象也是如此(。
因此,销毁它直接调用正确的析构函数~Derived1
。因此一切都很好。以下代码中出现问题:
Base* b = new Derived1();
delete b;
这隐式地调用b->~Base();
.由于~Base
不是虚拟的,因此~Derived1
不会被调用,因此你会得到UB。
std::unique_ptr<Base>
也是如此。但是,对于std::shared_ptr<Base>
来说并非如此,因为shared_ptr<>
构造函数是模板化的,并存储了构造它的实际对象的析构函数。也就是说,以下内容很好,并为两个对象调用正确的析构函数:
std::shared_ptr<Base> p1{new Derived1{});
std::shared_ptr<Base> p2 = std::make_shared<Derived1>();
至于你关于构造函数的问题,与数据成员的问题相同:即使它们在初始化器列表中缺失,它们仍然按照它们的声明顺序进行默认初始化,对于基类,则按从最远到最近的父级的顺序进行默认初始化。换句话说,你不能不初始化父类,它总是会发生。
问题 1:在任何一种情况下(1、2、3(,我是否有未定义的行为?为什么?
提供的代码示例中没有未定义的行为。 如果要尝试按住指向Base
的指针并通过该指针删除,则会出现未定义的行为。在提供的示例中,您知道要删除的具体类
问题 2:在两个派生类的构造函数的成员初始值设定项列表中(在上述特定情况下(中,构造 Base 不是必需的吗?
始终调用基类构造函数,无论是否显式调用它。如果没有显式调用,则将调用默认构造函数。如果没有默认的无参数构造函数,并且您不调用特定的构造函数,则代码将无法编译。
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 检查输入是否不是整数或数字
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 此代码是否违反一个定义规则
- 是否需要删除包含对象的"pair"?
- 是否可以从int转换为enum类类型
- 无论条件是否为true,if总是在c++中执行
- 如何找到大小'x'数组是否完全填充,在C++?
- 检查值是否在集合p1和p2中,但不在p3中
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 检查 std::shared_ptr<> 的当前底层类型是否为 T
- 在c++中检查长方体是否尽可能快地重叠(无迭代)
- GL_SHADERSTORAGE_BUFFER位置是否与其他着色器位置冲突
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- C/C++预处理器是否可以检测一些编译器选项
- 是否可以用"iostream"包装现有的TCP/OOpenSSL会话