C++ 对齐 new[]

问题描述 投票:0回答:2

概述

当浏览 operator new,operator new[] - cppreference.com 时,我们似乎有很多选项可以用于分配具有特定对齐要求的对象数组。但是,没有指定如何使用它们,而且我似乎找不到正确的 C++ 语法。

我可以以某种方式显式调用此运算符,还是编译器会自动推断重载? :

void* operator new[]( std::size_t count, std::align_val_t al );

查看Bartek的编码博客,似乎编译器会根据对齐要求是否大于

__STDCPP_DEFAULT_NEW_ALIGNMENT__
(在64位机器上通常为16)自动选择重载。

问题

在某些情况下是否可以手动为

new
运算符选择重载?有时我可能希望分配的块以某种方式对齐(我假设对齐始终是 2 的幂,并且可能大于 16)。

编译器的选择

在可预见的未来,我可能会使用 GCC 和 C++ >= 17。

c++ c++17 memory-alignment
2个回答
21
投票

operator new
的附加参数在类型之前的括号内传递:

#include <new>

int* allocate() {
    return new (std::align_val_t(16)) int[40]; // 128-bit alignment
    // will call `void* operator new[](size_t, align_val_t)`
}

0
投票

看来我来晚了一点:)

但是由于我也偶然发现了这个话题并提出了同样的问题,所以觉得有必要澄清一下

所以问题是,编译器似乎足够聪明,只有当它看到具有

new
对齐要求的类型时,即比
STDCPP_DEFAULT_NEW_ALIGNMENT
更对齐时,才能达到所述 special

的重载。

(cppreference 上的第 3,4 点)

  1. 由 new 调用,为对齐要求超过STDCPP_DEFAULT_NEW_ALIGNMENT的单个对象分配所需的存储空间。
  2. 由 new[] 调用,为对齐要求超过 STDCPP_DEFAULT_NEW_ALIGNMENT 的对象数组分配所需的所有存储空间。

这里(以及这里)是一个片段,表明它确实发生了:

#include <iostream>

void* operator new  ( std::size_t count, std::align_val_t al ) {
    std::cerr << "aligned alloc call with alignment=" << (std::size_t)al << " and count=" << count << std::endl;
    return ::operator new (count); ///< definitely not a good idea, but ok for this purpose
}

struct alignas(32) Overaligned {};

int main() {
    Overaligned* op = new Overaligned{};
    std::cerr << (const void*)op; // here just so that the compiler doesn't optimize away everything :)
}

所以是的,它会调用它:) 但如果您愿意,您可以手动分配内存,然后将东西放在那里:

::operator new[](sizeof(YourType), align_val_t{alignof(YourType)})
© www.soinside.com 2019 - 2024. All rights reserved.