我被告知引用變量必須在初始化列表中初始化,但爲什麼這是錯誤的?在初始化列表中初始化引用
class Foo
{
public:
Foo():x(0) {
y = 1;
}
private:
int& x;
int y;
};
因爲0是一個臨時對象嗎?如果是這樣,什麼樣的對象可以被引用綁定?可以接收地址的對象?
謝謝!
我被告知引用變量必須在初始化列表中初始化,但爲什麼這是錯誤的?在初始化列表中初始化引用
class Foo
{
public:
Foo():x(0) {
y = 1;
}
private:
int& x;
int y;
};
因爲0是一個臨時對象嗎?如果是這樣,什麼樣的對象可以被引用綁定?可以接收地址的對象?
謝謝!
0不是左值,它是右值。你不能修改它,但你試圖綁定到一個可以修改的引用。
如果您提供參考const
,它將按預期工作。考慮一下:
int& x = 0;
x = 1; // wtf :(
這顯然是一個不行。但const&
「可以綁定到臨時量(右值):
const int& x = 0;
x = 1; // protected :) [won't compile]
注意的是,臨時的生活時間是在構造函數中完成結束。如果你把靜態存儲你的不變,你將會很安全:
class Foo
{
public:
static const int Zero = 0;
Foo() : x(Zero) // Zero has storage
{
y = 1;
}
private:
const int& x;
int y;
};
長住引用必須綁定到一個lvalue
。基本上,正如你雄辯地說,一個具有明確地址的對象。如果它們被綁定到一個臨時的臨時將被銷燬,而引用仍然引用它,結果是未定義的。
短暫的const引用(局部函數變量和函數參數)可以綁定到臨時對象。如果是,那麼臨時保證在參考超出範圍之前不被銷燬。
示範代碼:
#include <iostream>
class Big {
public:
Big() : living_(true), i_(5) { // This initialization of i is strictly legal but
void *me = this; // the result is undefined.
::std::cerr << "Big constructor called for " << me << "\n";
}
~Big() {
void *me = this;
living_ = false;
::std::cerr << "Big destructor called for " << me << "\n";
}
bool isLiving() const { return living_; }
const int &getIref() const;
const int *getIptr() const;
private:
::std::string s_;
bool living_;
const int &i_;
char stuff[50];
};
const int &Big::getIref() const
{
return i_;
}
const int *Big::getIptr() const
{
return &i_;
}
inline ::std::ostream &operator <<(::std::ostream &os, const Big &b)
{
const void *thisb = &b;
return os << "A " << (b.isLiving() ? "living" : "dead (you're lucky this didn't segfault or worse)")
<< " Big at " << thisb
<< " && b.getIref() == " << b.getIref()
<< " && *b.getIptr() == " << *b.getIptr();
}
class A {
public:
A() : big_(Big()) {}
const Big &getBig() const { return big_; }
private:
const Big &big_;
};
int main(int argc, char *argv[])
{
A a;
const Big &b = Big();
const int &i = 0;
::std::cerr << "a.getBig() == " << a.getBig() << "\n";
::std::cerr << "b == " << b << "\n";
::std::cerr << "i == " << i << "\n";
return 0;
}
和輸出:
Big constructor called for 0x7fffebaae420
Big destructor called for 0x7fffebaae420
Big constructor called for 0x7fffebaae4a0
a.getBig() == A living Big at 0x7fffebaae420 && b.getIref() == -341121936 && *b.getIptr() == -341121936
b == A living Big at 0x7fffebaae4a0 && b.getIref() == 0 && *b.getIptr() == 0
i == 0
Big destructor called for 0x7fffebaae4a0
雖然構造函數中的具體示例如果聲明瞭成員變量'const',將會失敗。 – Omnifarious
@Omnifarious:這是怎麼回事? – GManNickG
臨時0被破壞時會發生什麼?如果它的地址被提取並且被解除引用,那麼如何? – Omnifarious