c++ - 我想我可以理解 N4140 中的 §5.3.4/11,但是扩展的分配函数的概念对我来说是不可理解的

标签 c++ language-lawyer new-operator c++14

以下两段是从 N4140 复制的(重点是我的)。

§5.3.4/11:

When a new-expression calls an allocation function and that allocation has not been extended, the new-expression passes the amount of space requested to the allocation function as the first argument of type std::size_t. That argument shall be no less than the size of the object being created; it may be greater than the size of the object being created only if the object is an array. For arrays of char and unsigned char, the difference between the result of the new-expression and the address returned by the allocation function shall be an integral multiple of the strictest fundamental alignment requirement (3.11) of any object type whose size is no greater than the size of the array being created. [ Note: Because allocation functions are assumed to return pointers to storage that is appropriately aligned for objects of any type with fundamental alignment, this constraint on array allocation overhead permits the common idiom of allocating character arrays into which objects of other types will later be placed. —end note ]

§5.4.3/12

When a new-expression calls an allocation function and that allocation has been extended, the size argument to the allocation call shall be no greater than the sum of the sizes for the omitted calls as specified above, plus the size for the extended call had it not been extended, plus any padding necessary to align the allocated objects within the allocated memory.

我能理解 §5.3.4/11,但是已扩展的分配函数的概念对我来说是不可理解的,如上文 §5.4.3/12 中所述。

最佳答案

此语言由 N3664: Clarifying Memory Allocation 添加当分配不是可观察行为的一部分时,它允许实现融合分配。换句话说,分配可以扩展

函数调用本身没有扩展,但是函数调用和分配可能会被省略并且分配可能会被集中到一个更大的分配中。

提案陈述了问题(强调我的):

As strict reading of the current C and C++ standards may lead one to conclude that the allocation strategy shall not consider any information not derivable from the sequence of new and delete expressions. In essence, the standards may exclude macro-optimization of allocation.

On the other hand, a strict reading of the standards may lead one to conclude that the implementation must make an allocation function call for each and every new expression. This reading may exclude micro-optimization of allocation.

并提议:

We propose to replace existing mechanistic wording with wording more precisely focused on essential requirements. The intent is to enable behavior that some existing compilers and memory allocators already have. For example, see TCMalloc

并进一步说:

An essential requirement on implementations is that they deliver usable memory, not that they have a particular sequence of allocation calls. We propose to relax the allocation calls with respect to new expressions.

  1. Within certain constraints, the number of allocation calls is not part of the observable behavior of the program. This enables implementations to reduce the number of allocation calls by avoiding them or fusing them.

  2. When avoiding or fusing allocations, the amount of space requested does not exceed that implied by the new expressions, with the exception of additional padding to meet alignment constraints. This means that the amount of space allocated does not increase peak allocation.

Because C++ class-specific memory allocators are often tuned to specific class sizes, we do not apply this relaxation to those allocators.

这可能导致完全省略分配,这在某些情况下可能会令人惊讶。我们可以看到以下来自 this question 的示例:

#include <new>  

int main()
{
    int* mem = new (std::nothrow) int[100];
    return 0;
}

clang 将其优化为 ( see it live via godbolt ):

main:                                   # @main
    xorl    %eax, %eax
    retq

这是允许的,因为没有观察到的行为受到影响,所以这属于 as-if rule 的范围.

关于c++ - 我想我可以理解 N4140 中的 §5.3.4/11,但是扩展的分配函数的概念对我来说是不可理解的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32991327/

相关文章:

c++ - std::vector 可视化工具在 std::vector<boost::variant> 上无法正常工作

julia - 结构字段的默认初始化状态?

c - 关于标准中的程序启动

c++ - 在 C++17 中排序的移位操作数

java - 字符串是 Java 中的对象,那我们为什么不使用 'new' 来创建它们呢?

android - 如何编译android ndk binder源码

c++ - 我可以将类模板添加到元组吗?

c++ - 为类的实例提供指向结构的指针

c++ - 分配字符串时 char* new 和 delete [] 错误

c++ - : list<object *> and list<object &> 之间的差异