运营商新实施可见性问题
Operator new implementation visibility issue
据说,作为一种好的做法,当为 class 实现运算符 new
的一种形式时,建议也必须实现所有其他形式。如果不这样做,由于 c++
不直观的可见性规则,可能会发生不好的事情。这些坏事是什么,它们是如何发生的?未实现的表单可以隐藏吗?
我假设您是在谈论重载全局运算符 new
函数与 class 特定的 operator new
.
TL;DR:如果您想要细粒度的内存控制,您可能希望考虑使用分配器范例,如标准容器。规则复杂,容易出错
实现所有这些的最常见原因是调用上下文混乱。通常,特定于 class 的 new 将根据全局运算符来实现。然而,这不是必需的,所以你会感到惊讶。
例如,假设您编写了 class A
和 class B
并且您想要控制分配。您为 A
和 B
.
编写覆盖
void *very_clever_allocator(size_t sz);
class A {
void* operator new(size_t sz) {
return very_clever_allocator(sz);
}
};
class B {
void* operator new(size_t sz) {
return very_clever_allocator(sz);
}
};
您的代码的善意用户写道:
void *operator(size_t sz) {
return incompatible_allocator(sz);
}
如果有人将您的 class 分配给 ::new A;
,则 class 特定版本将被忽略。所以突然之间,使用了一个不同的分配器。程序员可能不小心,调用了delete。既然你细心,你也定义了operator delete
。但是现在,您的 very_clever_allocator
不知道这个对象。这将是一个很难诊断的错误。
这并不常见,但由于这些规则非常复杂,通常使用 Allocator
更容易。如果您只是编写用于调试的代码,这一次没问题。
更多阅读:
https://eli.thegreenplace.net/2011/02/17/the-many-faces-of-operator-new-in-c
据说,作为一种好的做法,当为 class 实现运算符 new
的一种形式时,建议也必须实现所有其他形式。如果不这样做,由于 c++
不直观的可见性规则,可能会发生不好的事情。这些坏事是什么,它们是如何发生的?未实现的表单可以隐藏吗?
我假设您是在谈论重载全局运算符 new
函数与 class 特定的 operator new
.
TL;DR:如果您想要细粒度的内存控制,您可能希望考虑使用分配器范例,如标准容器。规则复杂,容易出错
实现所有这些的最常见原因是调用上下文混乱。通常,特定于 class 的 new 将根据全局运算符来实现。然而,这不是必需的,所以你会感到惊讶。
例如,假设您编写了 class A
和 class B
并且您想要控制分配。您为 A
和 B
.
void *very_clever_allocator(size_t sz);
class A {
void* operator new(size_t sz) {
return very_clever_allocator(sz);
}
};
class B {
void* operator new(size_t sz) {
return very_clever_allocator(sz);
}
};
您的代码的善意用户写道:
void *operator(size_t sz) {
return incompatible_allocator(sz);
}
如果有人将您的 class 分配给 ::new A;
,则 class 特定版本将被忽略。所以突然之间,使用了一个不同的分配器。程序员可能不小心,调用了delete。既然你细心,你也定义了operator delete
。但是现在,您的 very_clever_allocator
不知道这个对象。这将是一个很难诊断的错误。
这并不常见,但由于这些规则非常复杂,通常使用 Allocator
更容易。如果您只是编写用于调试的代码,这一次没问题。
更多阅读: https://eli.thegreenplace.net/2011/02/17/the-many-faces-of-operator-new-in-c