2014-12-02 22 views
2

Foo的行爲類似於循環迭代器。儘管我對此感到緊張,但下面的代碼編譯得很好,但會產生運行時錯誤。即使我從get_current()中刪除了const,我也會收到錯誤。當然,我可以返回一個指針,它會工作。然而,我會得到更好的安全性返回一個參考?返回對類成員容器元素的引用

#include <iostream> 
#include <array> 
#include <memory> 

class Foo 
{ 
public: 
    Foo(); 
    void next(); 
    const int& get_current() const; 
private: 
    std::array<std::unique_ptr<int>, 3> arr_; 
    unsigned i_; 
}; 

Foo::Foo() : i_(0) 
{ 
    arr_[0] = std::unique_ptr<int>(new int(5)); 
    arr_[1] = std::unique_ptr<int>(new int(6)); 
    arr_[2] = std::unique_ptr<int>(new int(7)); 
} 

void Foo::next() 
{ 
    ++i_; 
    i_ %= 3; 
} 

const int& Foo::get_current() const 
{ 
    return *arr_[i_]; 
} 

int main() 
{ 
    Foo foo; 
    int* p; 

    *p = foo.get_current(); 
    //do something with p 
    std::cout << *p << std::endl; 

    foo.next(); 
    *p = foo.get_current(); 
    //do something with p 
    std::cout << *p << std::endl; 

    return 0; 
} 

回答

2
int* p; 

這是一個未初始化的指針,沒有指向任何東西。解除引用會導致未定義的行爲。

*p = foo.get_current(); 

將無效指針取消引用。繁榮!

也許你希望它指向數組元素

p = &foo.get_current(); 

或者你想要的數組元素的副本

int n; 
n = foo.get_current(); 
1

*p = ...取消引用int* P無需它正確初始化。

在主代碼更改爲

int p; // Remove * 

p = foo.get_current(); 
//do something with p 
std::cout << p << std::endl; 

,或者如果你真的打算使用指針

const int* p; 

p = &foo.get_current(); 
    //^Take the address 
2

foo.get_current();很可能被返回const參考,但在那之後您正試圖在分配給*p時採取的副本。

分配到*p是什麼導致你麻煩的,因爲p未初始化。這是未定義的行爲並在您的情況下顯示爲運行時錯誤。

可能使用類似const int& p = foo.get_current();的代碼,但請注意參考只能綁定一次,因此您必須小心使用範圍確定。

,您可以使用std::shared_ptr<int>並使返回類型爲get_current(),並將您的代碼完全剝離裸指針。