【发布时间】:2018-10-24 00:19:16
【问题描述】:
给定以下程序:
#include <iostream>
#include <utility>
#include <vector>
#include <unordered_map>
#ifdef WITHPAIR
auto get_state() {
std::pair<std::vector<unsigned>, std::unordered_map<unsigned, unsigned&>> st;
auto& v = st.first;
auto& index = st.second;
v.assign({1u,2u,3u,4u});
index.insert({0u, v[0]});
index.insert({1u, v[1]});
index.insert({2u, v[2]});
index.insert({3u, v[3]});
return st;
}
#else
std::pair<std::vector<unsigned>, std::unordered_map<unsigned, unsigned&>> get_state() {
std::vector v{1u,2u,3u,4u};
std::unordered_map<unsigned, unsigned&> index{
{0u, v[0]},
{1u, v[1]},
{2u, v[2]},
{3u, v[3]}
};
return {v, index};
}
#endif
auto main() -> int {
auto [v, index] = get_state();
// auto [v, index] = std::move(get_state());
std::cout << v[0] << " " << index.at(0) << std::endl;
v[0] = 5;
std::cout << v[0] << " " << index.at(0) << std::endl;
std::cout << v[1] << " " << index.at(1) << std::endl;
v[2] = 17;
std::cout << v[2] << " " << index.at(2) << std::endl;
std::cout << v[3] << " " << index.at(3) << std::endl;
return 0;
}
http://coliru.stacked-crooked.com/a/f9e528074ae78c03
不使用-DWITHPAIR 进行编译以查看第二个函数的行为
函数get_state有两个版本。
只有第一个函数似乎具有正确的行为,并且在从函数返回时实际上使该数据可用(从链接的程序中可以看到);第二个函数的行为不是这样,并且 unordered_map 中的值与向量中的值不同。
我的问题是两个:
- 第一个函数的行为是否正确?是否是未定义的行为?
- 为什么第二个会改变向量?
【问题讨论】:
-
因为第二个有UB,第一个没有
-
@Slava 请将此作为答案。第二个的UB是多少?
-
第二个
v没有被移动,而是被复制,所以所有的引用都失效了。如果您明确移动v,它应该会修复它。 -
因为RVO导致第一个没有副本
-
是的,它被复制到,你也应该移动它,但是为了效率和一致性,但不移动
v会由于地图中的无效引用而带来 UB。
标签: c++ reference c++17 stdvector unordered-map