引用的地址是否总是等于原始地址? [英] Is always the address of a reference equal to the address of origin?

查看:137
本文介绍了引用的地址是否总是等于原始地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这看起来是一个非常基本的主题,但对我来说很重要.

This looks a very basic topic but very important to me.

以下示例显示参考变量的地址等于原始变量的地址.我知道这是我们从C/C ++概念中可以期待的.但是,是否在任何情况下都能始终保证这些地址相同?

The following example shows that the address of a reference variable is equal to the address of the original variable. I know this is what we can expect from the concept of C/C++. However, is it always guaranteed that these addresses are equal under any circumstance?

#include <iostream>
#include <vector>
#include <string>

class Point
{
public:
    double x,y;
};

void func(Point &p)
{
    std::cout<<"&p="<<&p<<std::endl;
}

int main()
{
    std::vector<Point> plist;
    plist.push_back({1.0,4.0});
    plist.push_back({10.0,20.0});
    plist.push_back({3.0,5.0});
    plist.push_back({7.0,0.4});

    std::cout<<"&plist[2]="<<&plist[2]<<std::endl;

    func(plist[2]);

    return 0;
}

结果:

&plist[2]=0x119bc90
&p=0x119bc90

推荐答案

不幸的是,许多人混淆了C ++引用的逻辑和物理含义.

Unfortunately, many people confuse logical and physical meaning of C++ references.

逻辑级别
关于C ++引用,我为自己找到了一件至关重要的事情:
一旦我初始化了引用,它就会变得 不可发音 .我所说的不可发音"是当您在运行时可执行代码中命名引用时,总是总是的事实-您会自动获得它所引用的变量,因此没有您可以触摸参考本身的方式.引用只是变量的备用名称(别名).

Logical level
There is a crucial thing I found for myself about C++ references:
As soon as I have initialized a reference, it becomes unpronounceable. And what I mean by "unpronounceable" is the fact that always when you name a reference in runtime executable code - you automatically get the variable it refers to, so there is no way you can touch the reference itself. Reference is just an alternative name (an alias) for a variable.

因此,无论您使用什么形式的可执行表达式,只要拥有类似int i_var = 10; int& i_ref = i;的内容,只要提及i_ref,实际上就是i_var.

So if you have something like int i_var = 10; int& i_ref = i; no matter what executable expression you form with it, any mentioning of i_ref would actually mean i_var.

此外,有些人认为将引用视为自引用指针"会有所帮助.因此,假设您有一个指针int* p,但是每次将其称为p时,实际上是指*p.例如,p = 10表示*p = 10,而&p表示&(*p)-p所指向的int的地址.这就是逻辑上引用的工作方式.

Also, some people find helpful to think of a reference as a "self-dereferencing pointer". So imagine you have a pointer int* p, but each and every time you refer to it as p you actually mean *p. For instance, p = 10 would mean *p = 10 and &p would mean &(*p) - the address of int which p is pointing too. That is how logically references work.

它也适用于您的代码.只要你有 Point &p = plist[2];(在调用func(plist[2])时发生),然后pplist[2]开始引用同一事物-某些Point对象,在plist中以2的索引存储.因此,现在&plist[2]&p 绝对相等.

It applies to your code too. As soon as you have Point &p = plist[2]; (occured when you called func(plist[2])) then p and plist[2] start reference to the same thing - some Point object stored by the index of 2 in plist. So now &plist[2] and &p are absolutely equal.

键入系统级别
如果您注意到,我使用的术语是运行时可执行代码"或可执行表达式".让我澄清一下.
编译器实际上知道ab之间的区别:

Type system level
If you noticed, I used terms "runtime executable code" or "executable expression". Let me clarify.
The compiler actually knows the difference between a and b:

int a = 0;
int& b = a;

std::cout << std::boolalpha 
          << std::is_same_v<decltype(a), decltype(b)>; // -> false

如您所见,ab类型不同.但是,std::is_same_v<decltype(a), decltype(b)>在编译时得到评估,所以我不认为它是可执行表达式".

As you see a and b types are different. However, std::is_same_v<decltype(a), decltype(b)> gets evaluated at compile time so i did not consider it as an "executable expression".

物理水平
请注意,到目前为止,我没有说,引用的地址被引用的变量是相同的.为什么?因为如果您从逻辑上考虑-他们不是.

Physical level
Notice, that until now I did not said that the address of a reference and the address of variable being referenced are the same. Why? Because if you think logically - they are not.

无论您是否喜欢,引用都必须以某种方式实现.我相信,在使用i_vari_ref的示例中,编译器将简单地将所有i_ref替换为i_var,并且引用"的任何物理表示形式都将不存在.另一方面,如果将引用存储在类中,则很可能使用指针来实现.
尽管实现是依赖于编译器的,但是如果引用实际上,则很显然该指针的地址与它所指向的对象的地址是不同的.

References have to be implemented in some way, whether you like it or not. I believe, in the example with i_var and i_ref compiler will simply replace all i_ref with i_var and any physical representation of "reference" will never exist. On the other hand, if you store reference inside a class it is likely to be implemented with a pointer.
Although, an implementation is compiler dependent, if reference actually is a pointer under the hood, it is obvious that the address of this pointer and the address of the object it is pointing to are different.

但是,您为什么要关心呢?您将永远不知道参考地址!在任何可执行表达式中,当您说i_ref时,您暗示i_var,还记得吗?:)

However, why should you care? You will never know the address of reference! In any executable expression, when you say i_ref you imply i_var, remember?:)

好吧,如果您真的很好奇引用的地址是什么",那么在一种情况下您可以弄清楚-引用是

OK, if you are really-really curious "what is the address of a reference", there is a one case when you can figure it out - when reference is a member of a class:

int main()
{
    int var = 10;
    int& real_ref = var;
    struct { int& ref; } fake_ref = { var };

    std::cout << &var       << std::endl;   // address of var
    std::cout << &real_ref  << std::endl;   // still address of var
    std::cout << &fake_ref  << std::endl;   // address of reference to var

    std::cout << sizeof var         << std::endl;    // size of var
    std::cout << sizeof real_ref    << std::endl;    // still size of var
    std::cout << sizeof fake_ref    << std::endl;    // size of reference to var

    return 0;
}

x64编译器上的输出:

Output on x64 compiler:

000000A9272FFBA4   <- same
000000A9272FFBA4   <- same
000000A9272FFBC0   <- different
4                  <- same
4                  <- same
8                  <- different (8 on 64 bit and 4 on 32 bit compiler)

这篇关于引用的地址是否总是等于原始地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆