用户定义分配器的非标准库放置新功能
Non-standard library placement new with user-defined allocators
非标准库放置new调用用户定义的运算符new:
class T {};
void* operator new(std::size_t s, T*) {
return new char[s];
}
int main() {
T* t;
new(t) T(); // calls operator new above
return 0;
}
但是,如果我没有错的话,标准放置new不会调用默认操作符new。这种分离允许标准分配器使用allocate()
中的运算符new来获取内存,并使用std::initialize_fill()或construct()
放置new来初始化内存
现在我不明白,当使用非标准放置new时,如何在自定义分配器中保持分配与初始化分离,因为非标准放置new总是调用用户定义的运算符new。是否应该在任何分配器中始终强制使用带有static_cast的标准放置new?
据我所见,您在某种程度上混淆了operator new()
和新运算符:尽管它们密切相关,但它们有不同的用途(如果回忆正确的话,Scott Meyers在Effective C++中有一个关于这方面的项目;或者,至少,他在早期版本中有一项,因为我现在看不到):
operator new()
的目的是使内存可用。通常,这相当于从某个地方分配内存,但在使用placementnew的特殊情况下,它实际上除了返回参数之外什么都不做- 新运算符的目的,即使用运算符调用表示法(而不是函数调用表示法)调用
operator new()
的表达式,包括两个步骤:- 它调用匹配的
operator new()
- 它调用匹配的构造函数在获得的位置中构造对象
- 它调用匹配的
也就是说,请注意,程序不允许替换运算符new
和delete
的放置版本!只允许替换用于实际内存分配的8个运算符(即operator new(size_t)
、operator delete(void*)
、相应的数组版本以及它们的std::nothrow_t
版本)。有关更多详细信息,请参见17.6.4.6[replacement.functions]。占位符版本实际上是为了传递它们的地址参数和(对于operator delete()
,在对象构造过程中抛出异常的情况下,满足存在性)。
分配器的allocate()
成员实际上是为了提供内存,例如通过调用malloc(n)
、operator new(n)
(但new char[n]
不是)、mmap()
页面等。它并不意味着实际构建任何对象(请参见表28中的17.6.3.5[allocater.requirements])。实际上,构造对象是分配器的construct()
成员的目的。事实上,这个函数本质上是调用placement new所必需的:
template <typename... A>
void allocator::construct(void* address, A&&... args) {
new(address) T(std::forward<A>(args)...);
}
(假设allocator
负责分配类型为T
的对象)。
在任何情况下,文档化的分配函数(malloc()
、operator new()
)都不会调用任何其他函数。它们可能在内部以通用函数的形式实现(可能是这样),但您可以在自己的分配函数中调用它们。当然,如果您要用自己的版本替换运算符,则不会调用标准库提供的版本。
- c++20[[no.unique_address]]中的新功能是什么
- 如果我想在没有更新编译器的情况下使用新功能,该怎么办?
- 重载算子新功能的限制
- C4204:使用的非标准扩展:非常量聚合初始值设定项
- 在双重继承的情况下如何处理非标准构造函数
- 设计模式,以避免不必要地添加抽象函数以适应新功能
- CMake 不编译具有非标准扩展名的文件
- 定义具有非标准签名的自定义映射比较器
- 我想获取点的属性,它报告错误 C3867:"point::output_x":非标准语法;使用"&"创建指向成员的指针
- 如何组织 git 工作流以修复错误并同时引入新功能
- 非标准语法,使用 & 创建指向成员的指针
- 在Qt中链接具有非标准名称的lib文件
- 新功能"synchronized"块在C++中提供了什么优势?
- 非标准语法使用 '&' 创建指向成员 C++ 的指针
- C++17 'inline variable' vs 'extern' 关键字继承自 C 的新功能
- WINAPI EnumWindowsProc:非标准语法;使用 & 创建指向成员的点
- Vulkan-hpp 是reinterpret_casting非标准布局类到另一个类.这合法吗?
- 'cv::Mat::type':非标准语法;使用 '&' 创建指向成员的指针
- 是否可以保证C++标准库容器调用可替换的新功能
- 用户定义分配器的非标准库放置新功能