下面的C++函数:初始化引用和变量在C++
int& ReturnAReference() {
/* Do something here */
}
有两种说法之间的任何差别:
int normalVariable = ReturnAReference();
int& referenceVariable = ReturnAReferene();
一个版本优于其他?
下面的C++函数:初始化引用和变量在C++
int& ReturnAReference() {
/* Do something here */
}
有两种说法之间的任何差别:
int normalVariable = ReturnAReference();
int& referenceVariable = ReturnAReferene();
一个版本优于其他?
对此:
int normalVariable = ReturnAReference();
normalVariable
是一个整数,和被分配了int值ReturnAReference()
引用的值。正如normalVariable
这样递增,分配或做任何其他事情不会影响任何ReturnAReference()
内部。
对此:
int& referenceVariable = ReturnAReference();
referenceVariable
是一个整数,否则将内部ReturnAReference()
的参考。由于此类递增,分配或做任何其他事情,referenceVariable
将影响无论ReturnAReference()
有内部。
什么是首选取决于你试图完成什么,但在许多情况下,第二种方法(使用referenceVariable
)违反了“封装”(http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)),这被认为是糟糕的设计。编辑:我应该补充说,如果ReturnAReference()返回的是一个变量在该函数中的本地引用,那么只要ReturnAReference()返回,该引用将无效。
我认为它首先会返回一个违反封装的引用,而不是调用者中的'referenceVariable'。 –
@ ben-voigt非常好的一点。 – wilsonmichaelpatrick
在参考文献已被初始化后,例如,经由
int i = 42;
int& r1 = i;
int& r2 = ReturnAReference();
int& r3(i);
int& r4{i}; // C++11
int& r5 = {i}; // C++11
它成为一个别名,即另一个名称,对象的已初始化。它是而不是另一个整数。 请注意,在C++标准的语言中,对象只是一个存储区域,不一定是类的一个实例。
作为参考是别名,如果与基准进行操作,你原来的对象(它已被初始化为一个)上运行:
int i = 42;
int& r = i;
// r is now an alias for i, both refer to the same object
r = 21; // a true assignment
std::cout << i; // will print 21
声明
int normalVariable = ReturnAReference();
介绍int
类型的该对象的新对象和名称:normalVariable
。该对象使用由ReturnAReference()
返回的对象进行初始化,这意味着返回对象的值被复制到名为normalVariable
的新对象中。
在另一方面,声明
int& referenceVariable = ReturnAReferene();
只引入了一个新的名字由ReturnAReference()
返回的对象。
如果你的函数会返回一个非参考int
,像int ReturnAnInt();
,声明
int& r = ReturnAnInt();
将成为非法,因为此函数返回的对象是一个临时,只生活直到这一行结束(在这种情况下)。在下一行中,名称r
将引用一个不再存在的对象,因此将非常量引用绑定到临时对象已被设为非法。
如果要修改由函数引用返回的变量或跟踪其值的任何更改,请使用int &。只要您访问该变量,就要确保您所引用的变量将存在。如果你只关心那个时候引用返回的变量的值,使用int。
仅供参考,std :: vector的运算符[]和at
函数通过引用返回以允许语法,如以下v.at(0) = 2
。
让我们假设你有如下定义:
int test = 4;
int& ReturnAReference() {
return test;
}
1)是否有这两种说法之间的区别:
int normalVariable = ReturnAReference();
在这种情况下,normalVariable
将持有返回值的副本(不是引用),因为赋值运算符会将返回值引用的值复制到normalVariable
。这意味着,在
normalVariable = 1;
normalVariable
现在是1,但test
仍将4.
但是,如果你有写
int& referenceVariable = ReturnAReferene();
,做
normalVariable = 1;
normalVariable
现在是1和test
也是1,因为normalVariable
只是test
的别名。
虽然返回参考时请小心。举例来说,如果你是做
int& ReturnAReference() {
int i = 0;
return i;
}
参考从ReturnAReference()
返回将不再有效,因为它是只在函数内部有效的,当它退出将被销毁。
2)一个版本比另一个更受欢迎吗?
在整数或其他原始类型的情况下,我宁愿int
返回值超过int&
,仅仅是因为一个int
小,不会复制昂贵的(它几乎总是适合在一个寄存器)。此外,如果引用引用了局部变量,则int&
返回值会带来安全问题。对于类或结构体,它总是依赖于它,但在通过引用或指针返回局部变量时必须小心。
@Floris是的,他们这样做。在visual studio 2012中检查。 – PeterM
它们都不是分配(严格来说),而是初始化。 – dyp
@DyP我应该改变标题吗? – PeterM