引用的地址是否总是等于原始地址? [英] Is always the address of a reference equal to the address of origin?
问题描述
这看起来是一个非常基本的主题,但对我来说很重要.
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])
时发生),然后p
和plist[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.
键入系统级别
如果您注意到,我使用的术语是运行时可执行代码"或可执行表达式".让我澄清一下.
编译器实际上知道a
和b
之间的区别:
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
如您所见,a
和b
类型不同.但是,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_var
和i_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屋!