首先,让我让这个问题更具体。
说
检查类型的析构函数是否可以被“忽略”
我是故意
检查类实例消失后是否没有副作用。
我在做什么:
我正在为我们的C ++项目编写垃圾收集库,我需要提高性能。如果我可以检测到传入类型T
在销毁时没有副作用,那么我可以检查所有活动对象,其余所有都是垃圾,可以标记为“垃圾”(典型的年轻一代)收集技术)。但是,如果有副作用,我必须扫描每个即将死亡的对象并运行它的析构函数。
例如:
struct S1 {
int i;
}; // can be ignored
struct S2 {
int i;
~S2() {
}
}; // can be ignored
struct S3 {
S3() {
std::cout << "S3()" << std::endl;
}
virtual ~S3() {
std::cout << "~S3()" << std::endl;
}
}; // can not be ignored, destructor has side effect
struct S4 {
S3 s3;
}; // can not be ignored, destructor has side effect(calling s3's destructor)
// this is the most tricky one I tried and failed.
struct S5 {
S3 s3;
~S5() {
}
}; // same with S4
struct S6 : public S3 {
};// can not be ignored, super destructor has side effect
struct S7 : public S1 {
};// can be ignored, super destructor does not have side effect
struct S8 {
virtual ~S8() = default;
}; // can be ignored
// which cannot use is_trivially_destructible
struct S9 : public S8 {
}; // can be ignored
我尝试将is_destructible
和is_trivially_destructible
合并,但这两个不能满足我的要求。尤其是示例4。
更多: 欢迎使用任何可以解决此问题的编译器特定功能。
答案 0 :(得分:5)
您需要std::is_trivially_destructible
类型的特征。看here。输出与期望值不同的唯一情况是companyNameChangeSubmit
。不幸的是,C ++缺乏将空的用户定义的析构函数视为琐碎的构造。
编辑:
无法从上述特征中排除关于S2
的条件,因此剩下的唯一选择就是创建自己的特征。这就需要在用户端做额外的工作,没有现成的东西。使用自定义谓词区分用户定义类型的方法有几种:
通过某种类型的继承存在:
virtual
(例如,键入别名-标签-transparent comparators的定义方式)
通过模板专业化(不是1和2独有):
class my_class : private can_be_forgotten_tag { ... };
template <typename T>
using can_be_forgotten_v =
std::is_trivially_destructible<T> ||
std::is_base_of<can_be_forgotten_tag, T>;
更重要的是,首先应该问的问题是,这是否已不是任何编译器自动为您完成的事情(生成带有或不带有析构函数调用的相同代码)。那样,最好检查一下自己。
P.S。我希望我们一直在考虑新的放置方式,否则会导致内存泄漏。