2013-08-19 78 views
4

下面的C++函数:初始化引用和变量在C++

int& ReturnAReference() { 
    /* Do something here */ 
} 

有两种说法之间的任何差别:

int normalVariable = ReturnAReference(); 
int& referenceVariable = ReturnAReferene(); 

一个版本优于其他?

+0

@Floris是的,他们这样做。在visual studio 2012中检查。 – PeterM

+0

它们都不是分配(严格来说),而是初始化。 – dyp

+0

@DyP我应该改变标题吗? – PeterM

回答

9

对此:

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()返回,该引用将无效。

+0

我认为它首先会返回一个违反封装的引用,而不是调用者中的'referenceVariable'。 –

+0

@ ben-voigt非常好的一点。 – wilsonmichaelpatrick

1

在参考文献已被初始化后,例如,经由

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将引用一个不再存在的对象,因此将非常量引用绑定到临时对象已被设为非法。

0

如果要修改由函数引用返回的变量或跟踪其值的任何更改,请使用int &。只要您访问该变量,就要确保您所引用的变量将存在。如果你只关心那个时候引用返回的变量的值,使用int。

仅供参考,std :: vector的运算符[]和at函数通过引用返回以允许语法,如以下v.at(0) = 2

1

让我们假设你有如下定义:

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&返回值会带来安全问题。对于类或结构体,它总是依赖于它,但在通过引用或指针返回局部变量时必须小心。