我在C++ 03标准中找到了以下片段5.3.5 [expr.delete] p3:
在第一个备选(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或者行为未定义.在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义.
快速回顾静态和动态类型:
struct B{ virtual ~B(){} };
struct D : B{};
B* p = new D();
Run Code Online (Sandbox Code Playgroud)
静态类型p是B*,而动态类型*p是D,1.3.7 [defns.dynamic.type]:
[ 例如:如果一个
p静态类型为"指向"的指针class B指向一个对象class D,B该表达式的动态类型*p是"D."]
现在,再次查看顶部的引用,这意味着如果我正确的话,下面的代码会调用未定义的行为,无论是否存在virtual析构函数:
struct B{ virtual ~B(){} };
struct D : B{};
B* p = new D[20];
delete [] p; // undefined behaviour here …Run Code Online (Sandbox Code Playgroud) 如果我的类没有动态分配任何内存,我们是否需要虚拟析构函数?
例如
class A
{
private:
int a;
int b;
public:
A();
~A();
};
class B: public A
{
private:
int c;
int d;
public:
B();
~B();
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们需要将A的析构函数标记为虚拟吗?
一般问题:如果不考虑它是否是一个好主意,我如何将一个隐式转换运算符添加到已经定义的类中?例如,假设我想要unique_ptr <T>隐式转换为T*,但我不能只添加成员转换运算符,因为我无法更改unique_ptr类的定义.
选项:
是否有一些c ++巫毒可以用来实现这一点而无需创建成员函数?
答案 - 远:没有.
无法从无法在代码中修改的类型添加隐式转换.
只是......悲伤.
我可以从std :: unique_ptr派生并添加我自己的成员转换函数吗?这有什么严重的缺点吗?
Answer-So-Far:是的(来自vsoftco)
下行尚未确定.到目前为止继承自std :: unique_ptr,继承其构造函数,并声明一个隐式转换运算符,几乎没有任何需要编写的代码.
我将不得不在余生中生活吗?
答案 - 迄今为止:我们会看到......
如果我可以选择2运行而没有任何严重的副作用或负担,我会测试一段时间并报告我是否认为值得.走着瞧!
示例代码:
#include <algorithm>
#include <memory>
#include <vector>
struct MyClass
{
MyClass(int v) : value(v) {}
int value;
};
int main()
{
auto vec = std::vector<std::unique_ptr<MyClass>>();
vec.push_back(std::make_unique<MyClass>(1));
vec.push_back(std::make_unique<MyClass>(2));
// error C2664: 'void (__vectorcall *)(MyClass *)' : cannot convert argument 1 from 'std::unique_ptr<MyClass,std::default_delete<_Ty>>' to 'MyClass *'
std::for_each(std::begin(vec), std::end(vec), [](MyClass* myClass)
{
myClass->value += 3;
});
}
Run Code Online (Sandbox Code Playgroud) BaseClass * p = new DerivedClass();
delete p;
Run Code Online (Sandbox Code Playgroud)
我知道第二行将调用基类的析构函数,如果它没有虚拟析构函数和派生类的析构函数,如果它有,但会delete正确释放内存(让我们说BaseClass's对象占用8个字节的空间,DerivedClass一个12 - 它会释放8或12个字节)并在任何一种情况下摆脱对象?