如果我运行以下代码,则输出
key: 3, value: 4
key: 32767, value: 1971892984
我错误地创建了这个例子,我知道我的KV类不应该在其成员变量中存储引用。但我无法解释这个结果。
我原以为key_
和value_
是堆栈上i
和j
的别名。所以它们在传递给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;
}
答案 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
来限制意外行为的范围。