c++ - 内存中类位置的成员是否依赖于类定义中类成员的位置?
问题描述
我有一部分连锁班
template <typename T>
class Part
{
public:
part* prev;
part* next;
T data;
}
T 的大小现在未定义,我认为最好将它放在内存的末尾。
例如,如果我向右移动 8 个字节,那么我肯定会走到下一个类成员的开头(在 64 位系统上),如果我先放 T,那么我不知道我会在哪里去。我会影响类成员在内存中的位置,还是编译器会按照他的意愿做所有事情?
我可以帮助使用它吗?
解决方案
我不能肯定地说,因为它是在各种编译器之间实现定义的......
我将此添加到您的代码中:
template <typename T>
class Part {
public:
Part* prev;
Part* next;
T data;
};
template<typename T>
Part<T> makeClass(T value) {
Part<T> part{};
part.data = value;
return part;
}
int main() {
auto p = makeClass(12);
return 0;
}
我在之间测试了它x86-64 clang (trunk)
,x86-64 gcc (trunk)
并且x64 msvc v19.24
在编译器资源管理器上发现这里所有的编译器设置都设置为-std=c++17 -O3
.
如果我们查看三者之间生成的程序集,我们会看到以下内容:
铛
main: # @main
xor eax, eax
ret
海合会
main:
xor eax, eax
ret
MSVC
part$ = 0
$T1 = 64
value$ = 72
Part<int> makeClass<int>(int) PROC ; makeClass<int>, COMDAT
$LN3:
mov DWORD PTR [rsp+16], edx
mov QWORD PTR [rsp+8], rcx
push rsi
push rdi
sub rsp, 40 ; 00000028H
lea rax, QWORD PTR part$[rsp]
mov rdi, rax
xor eax, eax
mov ecx, 24
rep stosb
mov eax, DWORD PTR value$[rsp]
mov DWORD PTR part$[rsp+16], eax
lea rax, QWORD PTR part$[rsp]
mov rdi, QWORD PTR $T1[rsp]
mov rsi, rax
mov ecx, 24
rep movsb
mov rax, QWORD PTR $T1[rsp]
add rsp, 40 ; 00000028H
pop rdi
pop rsi
ret 0
Part<int> makeClass<int>(int) ENDP ; makeClass<int>
$T1 = 32
$T2 = 56
p$ = 80
main PROC
$LN3:
push rsi
push rdi
sub rsp, 120 ; 00000078H
mov edx, 12
lea rcx, QWORD PTR $T2[rsp]
call Part<int> makeClass<int>(int) ; makeClass<int>
lea rcx, QWORD PTR $T1[rsp]
mov rdi, rcx
mov rsi, rax
mov ecx, 24
rep movsb
lea rax, QWORD PTR p$[rsp]
lea rcx, QWORD PTR $T1[rsp]
mov rdi, rax
mov rsi, rcx
mov ecx, 24
rep movsb
xor eax, eax
add rsp, 120 ; 00000078H
pop rdi
pop rsi
ret 0
main ENDP
查看从各种编译器生成的程序集可能会帮助您确定代码中发生的情况及其数据对齐方式。在级别 3 使用优化器查看这些值后,将其更改为级别 2、1,然后是 1,然后查看生成的程序集的差异。这可能会给你一些见解!
来自专业人士的提示 - 相信你的编译器!
推荐阅读
- android - 指定的 Gradle 发行版“https://services.gradle.org/distributions/gradle-4.6-all.zip”似乎不包含 Gradle 发行版
- javascript - 点击后HTML更改按钮名称
- git - Jenkins 管道从 windows jenkins 服务器推送 git 标签
- vuejs2 - bootstrap-vue:b-table 如何防止可选表在某些情况下选择更改
- jquery - 如何重置由 Api 响应通过 javascript 呈现的表单的值
- linux - 获取 tmux 中其他窗格的标准输入
- jenkins - 在 Jenkins 管道中添加 SVN 结帐时出现凭据错误
- asp.net - 无法从文本框控件接收数据到 liqtosql 实体
- php - 如何获取 laravel-admin 网格值
- javascript - 如何在 IP 本身中使用额外参数更改 url?