有没有办法找到参考的地址?

时间:2009-12-23 04:56:44

标签: c++ reference

有没有办法找到参考地址?

使其更具体:变量本身的地址,而不是它初始化的变量的地址。

11 个答案:

答案 0 :(得分:57)

引用没有自己的地址。虽然引用可以实现为指针,但是不需要或保证这一点。

The C++ FAQ说得最好:

  

与指针不同,一旦引用就是   绑定到一个对象,它不可能   “重新安置”到另一个对象。该   引用本身不是一个对象(它   没有身份;以地址为   引用为您提供地址   指称;记住:参考   是它的指示物。)

请在此处查看我的回答comprehensive list of how references differ from pointers

引用是它的指示

答案 1 :(得分:34)

即可。无法获取参考地址。
这是因为引用不是对象,它是别名(这意味着它是对象的另一个名称)。

int  x = 5;
int& y = x;

std::cout << &x << " : " << &y << "\n";

这将打印出相同的地址 这是因为'y'只是对象'x'的另一个名称(别名)。

答案 2 :(得分:20)

ISO标准说得最好:

  

不应引用引用,不引用引用数组,也不引用引用指针。

我不喜欢很多人在这里使用的逻辑,你不能这样做,因为引用不是“保证在任何地方只是一个指针”。正如int x可能只是一个没有地址的处理器寄存器,但在使用& x时神奇地成为一个内存位置,编译器仍然可以允许你想要的东西。

过去,许多编译器确实允许您提出的要求,例如

int x, y;
int &r = x;
&r = &y; // use address as an lvalue; assign a new referent

我刚检查过,GCC会编译它,但是警告措辞强烈,结果程序坏了。

答案 3 :(得分:12)

没有

正如Bjarne Stroustrup在TC ++ PL中所说,引用可以被认为是现有实体(对象或函数)的另一个名称。虽然这并不总是对实现引用的底层低级机制的最精确描述,但它是对引用在语言级别实现的概念的非常好的描述。毫不奇怪,该语言无法获得引用本身的地址。

在语言级别,参考不能保证占用存储空间,因此一般情况下它没有地址。

答案 4 :(得分:9)

来自同一问题的另一个例子:$ 8.3.2 / 3 - “未指明引用是否需要存储(3.7)。”。

因此,C ++标准允许编译器/运行时实现者选择引用是否位于单独的内存位置。但请注意,如果它确实存在于单独的内存位置,则无法以符合标准的方式找到其地址。所以不要这样做。

如果您根据C ++标准的定义获取引用的地址,您将获得它所引用的地址,而不是引用的地址,如果事实上该引用甚至作为单独的实体存在于运行环境与否。

答案 5 :(得分:7)

只需使用'&amp;'运营商。 例如:

int x = 3;
int &y = x;
cout<<&y<<endl;

这将返回x的地址,因为y只不过是x的地址。

答案 6 :(得分:4)

不可靠,因为引用不必在可寻址存储器中具有唯一的位置。

答案 7 :(得分:2)

不是单独的。如果你想要它的“地址”,就把它推到一个结构或类中。即使这样,也不一定能保证让你在你想要做的事情附近使用指针。如果需要校样,则引用的sizeof等于引用类型。尝试使用char&amp;并看到。

答案 8 :(得分:1)

有可能,但不严格使用C ++。由于引用作为函数的参数传递,因此其值将存储在堆栈或寄存器中。 这取决于硬件架构。访问这些值将需要内联汇编。请参阅您正在使用的处理器的参考手册,以确定堆栈行为和寄存器地址。 损坏堆栈或寄存器很容易导致BSOD,数据丢失甚至永久性损坏您的系统。 请务必小心谨慎。

答案 9 :(得分:0)

如果将引用实现为结构的成员,则可以获取其地址:

struct TestRef{
  int& r;
  int i;
  TestRef(int& ref): r(ref){
  }
};

引用确实是一个指针(在我的情况下使用Xcode编译器),您可以更新其值以将引用重新分配给新变量。 为此,我们需要找出引用的地址并将其值欺骗到其他变量的地址

现在,引用TestRef.r的地址是TestRef对象的地址。因为r是TestRef的第一个成员。

您可以通过更新TestRef.r内存中的值存储来重新分配引用。

下面的代码显示,您可以获得引用地址,并且可以将引用重新分配给差异变量。注意:我的操作系统是X64操作系统(我使用Xcode MacBook Pro 2015,MacOs 10.15.1)。

#include <iostream>
using namespace std;

struct TestRef{
  int& r;
  int i;
  TestRef(int& ref): r(ref){}
};

int main(int argc, const char * argv[]) {
  int i = 10;
  int j = 11;
  TestRef r(i); // r.r is reference to i

  cout << r.r << " " << i << " " << j << endl; // Output: 10 10 11

  int64_t* p = (int64_t*)&r; // int32_t in 32 bit OS; 
  // Note: 
  // p is the address of TestRef r and also the address of the reference r.r
  // *p is the address of i variable
  //
  // Difficult to understand? r.r indeed a pointer to i variable 
  // *p will return the address inside the memory of r.r
  // that is the address of i variable
  // this statement is true: *p == &i  
  // ------>
  // now we change the value of *p to the address of j 
  // then r.r will be the reference of j instead the reference of i

  *p = (int64_t)&j;          // int32_t in 32 bit OS; 

  cout << r.r << " " << i << " " << j << endl; // Output: 11 10 11
  return 0;
}

实际上,您可以变通重新分配参考,例如黑客。

答案 10 :(得分:-2)

//YES reference varies
//but a little trick in the compiler

    int i = 333;
    int j = 444;
    int &ref = i;                   //ref=i value
    int* p = nullptr;


    printf("ref=%d\n", ref);        //333  i value

    *(&p + 3) = &j;                 //&ref=j

    printf("ref=%d\n", ref);        //444  j value