2015-04-01 61 views
0

如果我運行下面的代碼,它輸出,參考文獻沒有給預期的結果

key: 3, value: 4 
key: 32767, value: 1971892984 

我創造了這個例子錯誤,我知道我的KV類不應該被存儲在它的成員變量的引用。但是我無法解釋這個結果。

我原本以爲key_value_是堆棧上的ij的別名。所以它們在傳遞到cout << first時應該仍然有效,因爲它們還沒有被取走。但我甚至無法猜測爲什麼輸出會有所不同。這是我看到的特定於實現的細節嗎?還是有什麼更深層的理解?

#include <iostream> 

using namespace std; 

template <typename K, typename V> 
class KV { 
public: 
    KV(): key_(), value_() {} 
    KV(K& key, V& value): key_(key), value_(value) {} 

    K key() const { return key_; } 
    V value() const { return value_; } 


private: 
    K& key_; 
    V& value_; 
}; 

template <typename T, typename U> 
ostream& operator<<(std::ostream &strm, const KV<T, U> &a) { 
    cout << "key: " << a.key() << ", value: " << a.value() << endl; 
    strm << "key: " << a.key() << ", value: " << a.value() << endl; 
} 

template <typename T, class U> 
KV<T, U> make_kv(T t, U u) { 
    KV<T,U> kv(t, u); 
    return kv; 
} 

int main() { 
    int i = 3, j = 4; 
    KV<int, int> first = make_kv(i, j); 
    cout << first; 

    return 0; 
} 

回答

4

您有懸掛引用,因此存在未定義的行爲。其原因是,你在make_kv存儲引用本地對象,其範圍引用的函數本身:

template <typename T, class U> 
KV<T, U> make_kv(T t, U u) { 
    KV<T,U> kv(t, u); 
    return kv; 
} // t, u end here!!! 

你可以通過修改make_kv採取引用解決該問題:

template <typename T, class U> 
KV<T, U> make_kv(T& t, U& u) { 
    KV<T,U> kv(t, u); 
    return kv; 
} 

注意:您必須確保您瞭解持有引用的類型的複製和分配語義。將參考const限制爲意外行爲的範圍可能是一個想法。