给定以下 c++ 函数:
int& ReturnAReference() {
/* Do something here */
}
这两种说法有什么区别:
int normalVariable = ReturnAReference();
int& referenceVariable = ReturnAReferene();
一个版本优于另一个版本吗?
给定以下 c++ 函数:
int& ReturnAReference() {
/* Do something here */
}
这两种说法有什么区别:
int normalVariable = ReturnAReference();
int& referenceVariable = ReturnAReferene();
一个版本优于另一个版本吗?
关于这一点:
int normalVariable = ReturnAReference();
normalVariable
是一个整数,并被分配了ReturnAReference()
引用的 int 的值。因此,增加、分配或做任何其他事情都normalVariable
不会影响ReturnAReference()
内部的任何事情。
关于这一点:
int& referenceVariable = ReturnAReference();
referenceVariable
是对一个整数的引用,否则它会在ReturnAReference()
. 因此,增加、分配或做任何其他事情referenceVariable
都会影响ReturnAReference()
内部的任何事情。
首选取决于您要完成的工作,但在许多情况下,第二种方法(使用referenceVariable
)违反了“封装”(http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)),即被认为是糟糕的设计。
编辑:我应该补充一点,如果 ReturnAReference() 返回对该函数中本地变量的引用,则该引用将在 ReturnAReference() 返回时立即无效。
在一个引用被初始化之后,例如通过
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 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&
,仅仅是因为 anint
很小并且复制起来不会很昂贵(它几乎总是适合寄存器)。此外,int&
如果引用引用局部变量,则返回值会带来安全问题。对于类或结构,它总是取决于,但是当通过引用或指针返回局部变量时必须小心。
如果要修改函数引用返回的变量,或者要跟踪对其值的任何更改,请使用 int&。只要您访问它,您就可以确保所引用的变量一直存在。如果您只关心此时引用返回的变量的值,请使用 int.
仅供参考,std::vector 的运算符 [] 和at
函数通过引用返回,允许语法如下v.at(0) = 2
。