正在获取在寄存器中传递的参数的地址 C++中具有传递值,调用方构造被调用方使用的副本。在x64 ABI中,一些参数在寄存器中传递。寄存器没有地址

正在获取在寄存器中传递的参数的地址 C++中具有传递值,调用方构造被调用方使用的副本。在x64 ABI中,一些参数在寄存器中传递。寄存器没有地址,c++,cpu-registers,calling-convention,C++,Cpu Registers,Calling Convention,因此,假设我有以下类: class Self_Pointer { Self_Pointer* self; Self_Pointer(const Self_Pointer& obj) : self(this) {} } 当作为参数传递时,它接受指向自身的指针。现在我有了这个函数: f(Self_Pointer x) {} f()。f()的调用方必须在寄存器中创建副本。因此,调用方将在寄存器中的Self_指针上运行构造函数。但是,寄存器没有地址,因此无法运行构造函数。这一

因此,假设我有以下类:

class Self_Pointer
{
    Self_Pointer* self;
    Self_Pointer(const Self_Pointer& obj) : self(this) {}
}
当作为参数传递时,它接受指向自身的指针。现在我有了这个函数:

f(Self_Pointer x) {}
f()。
f()
的调用方必须在寄存器中创建副本。因此,调用方将在寄存器中的Self_指针上运行构造函数。但是,寄存器没有地址,因此无法运行构造函数。这一困境如何解决


[编辑:根据Steve Jessop的回答,将类的ctor修复为复制ctor。]

不,您不能。您得到的地址始终是RAM的虚拟地址。不能直接访问C++中的登记地址。< /P> < P>不,不能。您得到的地址始终是RAM的虚拟地址。不能直接访问C++中的寄存器地址。

< P>使用登记器(或堆栈,用于参数传递)是特定编译器的实现细节。为了获得要传递给函数的地址,编译器将寄存器的值复制到内存中的一个临时位置(通常在堆栈上),将其地址传递到它需要去的任何地方,然后根据需要将数据从临时位置加载回同一个寄存器。

使用寄存器(或堆栈)参数传递是特定编译器的实现细节。为了获得要传递给函数的地址,编译器将寄存器的值复制到内存中的临时位置(通常在堆栈上),将其地址传递到需要传递的任何位置,然后根据需要将数据从临时位置加载回同一寄存器。

首先,
Self\u指针的副本不指向自身。它指向原始,因为编译器生成的复制构造函数将
self
的值从原始复制到副本

因此,当您通过复制将对象传递到
f
时,实际上
x
并不指向自身

如果您通过为
Self\u指针
编写合适的副本构造函数来修复此问题,则需要实现以确保
x
具有地址。如果这意味着不在寄存器中传递它,那么它就不会在寄存器中传递。通常,ABI不会在寄存器中传递结构,除非它们是聚合类型,而您的示例不是这样,因为它有一个用户定义的构造函数

另一个例子是,考虑:

void foo(int i) {
   std::cout << &i << '\n';
}
void foo(inti){

std::cout首先,
Self\u指针的副本不指向自身。它指向原始指针,因为编译器生成的副本构造函数将
Self
的值从原始指针复制到副本

因此,当您通过复制将对象传递到
f
时,实际上
x
并不指向自身

如果您通过为
Self\u指针
编写合适的复制构造函数来修复此问题,则需要实现以确保
x
具有地址。如果这意味着不在寄存器中传递它,则不会在寄存器中传递它。通常,ABI不会在寄存器中传递结构,除非它们是聚合类型,您的示例不是这样的,因为它有一个用户定义的构造函数

另一个例子是,考虑:

void foo(int i) {
   std::cout << &i << '\n';
}
void foo(inti){

std::cout如果你真的想知道,查看生成的程序集总是最好的方法。我试过了,但我看不懂程序集。如果你真的想知道,查看生成的程序集总是最好的方法。我试过了,但我看不懂程序集。