Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对齐是如何影响内存布局和新位置的行为的?_C++_Memory Alignment_Placement New_Memory Layout_Alignas - Fatal编程技术网

C++ 对齐是如何影响内存布局和新位置的行为的?

C++ 对齐是如何影响内存布局和新位置的行为的?,c++,memory-alignment,placement-new,memory-layout,alignas,C++,Memory Alignment,Placement New,Memory Layout,Alignas,我们读了很多关于对齐的内容,以及它的重要性,例如对于放置new用法,但我想知道-它到底是如何改变内存的布局的 显然,如果我们这样做 char buffer[10]; std::cout << sizeof buffer; 根据GCC 8.2,未进行优化,导致以下装配: operator new(unsigned long, void*): push rbp mov rbp, rsp mov QWORD PTR [rbp-8], rdi

我们读了很多关于对齐的内容,以及它的重要性,例如对于放置
new
用法,但我想知道-它到底是如何改变内存的布局的

显然,如果我们这样做

char buffer[10];
std::cout << sizeof buffer;
根据GCC 8.2,未进行优化,导致以下装配:

operator new(unsigned long, void*):
    push    rbp
    mov     rbp, rsp
    mov     QWORD PTR [rbp-8], rdi
    mov     QWORD PTR [rbp-16], rsi
    mov     rax, QWORD PTR [rbp-16]
    pop     rbp
    ret
main:
    push    rbp
    mov     rbp, rsp
    sub     rsp, 16
    lea     rax, [rbp-12]
    mov     rsi, rax
    mov     edi, 4
    call    operator new(unsigned long, void*)
    mov     eax, 0
    leave
    ret
让我们通过删除
alignas(int)
部分来稍微更改代码。现在,生成的部件略有不同:

operator new(unsigned long, void*):
    push    rbp
    mov     rbp, rsp
    mov     QWORD PTR [rbp-8], rdi
    mov     QWORD PTR [rbp-16], rsi
    mov     rax, QWORD PTR [rbp-16]
    pop     rbp
    ret
main:
    push    rbp
    mov     rbp, rsp
    sub     rsp, 16
    lea     rax, [rbp-10]
    mov     rsi, rax
    mov     edi, 4
    call    operator new(unsigned long, void*)
    mov     eax, 0
    leave
    ret
值得注意的是,它只在
lea
指令上有所不同,其中第二个参数是
[rbp-10]
,而不是
[rbp-12]
,正如我们在
alignas(int)
版本中所做的那样

请注意,我通常不理解组装。我不会写汇编,但我能读一些。据我所知,这种差异只是改变了内存地址的偏移量,它将保持我们的位置-
new
ed
int

但它实现了什么?我们为什么需要这个?假设我们有一个
缓冲区
数组的“通用”表示,如下所示:

[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
现在,我假设,在放置-
new
ing
int
(有或没有对齐)之后,我们将得到如下结果:

[x] [x] [x] [x] [ ] [ ] [ ] [ ] [ ] [ ]
其中,
x
表示
int
的单个字节(我们假设
sizeof(int)==4


但我肯定错过了什么。还有更多,我不知道是什么。通过将
缓冲区
int
对齐,我们到底能实现什么?如果我们不将其对齐,会发生什么情况?

在某些体系结构上,类型必须对齐才能使操作正常工作。例如,
int
的地址可能需要是4的倍数。如果它没有如此对齐,那么对内存中的整数进行操作的CPU指令将无法工作

即使在数据没有很好地对齐时一切都正常工作,对齐对性能仍然很重要,因为它确保整数等不会跨越缓存边界


char
缓冲区与整数边界对齐时,不会影响新放置的工作方式。它只是确保您可以使用placement new在缓冲区的开头放置一个
int
,而不违反任何对齐约束。它通过确保缓冲区的地址是4字节的倍数来实现这一点。

当您在同一缓冲区中放置新的
char
,然后在“之后”立即放置新的
int
。@MooingDuck因此假设我永远不会将我放置的类型混入我的缓冲区(假设我以一种非常简单的方式模仿
std::vector
的缓冲区),我可以不用对齐就可以做到这一点?不,对齐仍然是一个问题,只是在混合类型之前很难注意到这个问题。相关,但不完全回答这个问题:
[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
[x] [x] [x] [x] [ ] [ ] [ ] [ ] [ ] [ ]