2016-04-28 86 views
5

我碰到下面的代码来:C++引用和返回值

class MyClass { 

// various stuff including ... 
    double *myarray; 

    double &operator() (const int n){ 
     return myarray[n]; 
    } 
    double operator() (const int n) const { 
     return myarray[n]; 
    } 

// various other stuff ... 
} 

那么究竟是什么在“()”这两个重载的实际差别?我的意思是,我知道“第一个返回对双精度的引用,第二个返回双精度”,但这实际上意味着什么?我什么时候可以使用那个,什么时候使用另一个?第二个(返回一个double)看起来很安全和直接。第一个在某种程度上有危险吗?

+4

你确定当你看到'double operator()(const int n)'你实际上没有看到'double operator()(const int n)cont'吗? – NathanOliver

+0

简而言之:第一个支持写作;如果对象是const,则第二个可用。 –

+0

[C++中指针变量和引用变量之间的区别是什么?]可能的重复(http://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-和-a-reference-variable-in) – piyushj

回答

6

他们在第一个不同,您可以修改您的数组元素,而第二个只返回值,所以您可以:

有:双&运营商()

MyClass mm; 
mm(1) = 12; 

也:

std::cout << mm(1); 

有:双运营商()

// mm(1) = 12; // this does not compile 
std::cout << mm(1); // this is ok 

还,返回​​基准来operator[]时,当您使用std::vector::operator[]喜欢为多见。

btw。其共同有operator()两个版本 - 一个常量和第二个非常量。常量版本将在const对象上调用,而第二个版本则在非const上调用。但通常他们的签名是:

double& operator() (const int n); 
const double& operator() (const int n) const; 
+0

'mm(1)= 12'啊。光线继续。谢谢。 –

+0

Re:你最后一句话,通过值传递方法应该读取'double operator()(const int n)const'我做了编辑。这能解决问题吗? –

+0

@ bob.sacamento是的,我已经更新了答案 – marcinj

4

通常,指针和引用之间的区别在于指针可以被改变,并且也可以指向nullptr,即没有任何改变。参考资料已修复。

但是在这个例子中,operator()不返回一个引用,而是返回一个值的副本,即改变这个方式检索的值不会改变类中的double

如果它确实返回了双重&,那么您可以交替使用这两种方法(当然在用法中使用不同的符号),并且提供这两种方法对于这个类的用户来说仅仅是一个受欢迎的方便。

4

这是什么意思?

这意味着第二个方法返回值,即它使array-item/double的副本并将该副本返回给调用者。第一个方法返回引用,即它不会复制double,而是返回对原始/数组中double的位置的引用,然后调用代码可以使用该引用直接访问内联对象,数组加倍,如果它想。 (如果有帮助,返回参考的间接语义有点像指针语义,除了与一种语法,更类似于传统的C/C++按值的功能)当我将使用一个和

我什么时候会用另一个?

按值方法更安全,因为调用未定义行为的机会较少;通过引用方法给你更多的灵活性(例如,调用者可以通过写入他作为返回值收到的引用来更新数组中的项),并且在某些情况下它可能更有效(例如,返回引用可以避免需要复制对象,如果对象很大或很复杂,这可能是一个昂贵的操作)。对于像double这样的小对象,返回值可能比返回by-reference更高效。

[by-reference method]是否有某种危险性?

它可以是 - 例如,如果你要返回引用到自动/堆栈变量,这会导致不确定的行为,因为变量将被销毁之前调用代码可以使用它:

double & dont_ever_do_this() 
{ 
    double x = 5.0; // x will be destroyed as this method returns! 
    return x;  // so returning a reference to x is a silly thing to do 
} 

同样,在MyClass示例中,如果调用方持有返回的引用,然后在myarray被删除后尝试使用它,则调用方将读取(或写入)不是更长的有效期,这将导致未定义的行为(读取:坏事)发生。

当然,返回一个非const引用意味着调用者可以更改返回的数组项的内容,而不需要您的类意识到它,这可能不是您想要允许的。

+0

你确定*你在这个答案的几个地方没有“第一个”和“第二个”混在一起? – WhozCraig

+0

哈,你说得对。我会解决这个问题。 –

2

您可以通过此链接查看值类别。 http://en.cppreference.com/w/cpp/language/value_category

double& operator()如果您有左值表达式,可以使用像左值(用于分配,打印等)

MyClass class; 
class(7) = 21; 

std::cout << class(7); 

而且在double operator() const如果你有右值表达式。 在这种情况下,您也可以使用它与const对象。