参考文献未给出预期结果

时间:2015-04-01 05:35:52

标签: c++

如果我运行以下代码,则输出

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;
}

1 个答案:

答案 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来限制意外行为的范围。