在地图中分配值时,正确的评估顺序是什么?
What is the proper evaluation order when assigning a value in a map?
我知道编译器通常是代码中错误的最后一件事,但对于以下 C++ 代码的以下行为(从实际项目中提取),我看不到任何其他解释:
#include <iostream>
#include <map>
int main()
{
auto values = { 1, 3, 5 };
std::map<int, int> valMap;
for (auto const & val : values) {
std::cout << "before assignment: valMap.size() = " << valMap.size();
valMap[val] = valMap.size();
std::cout << " -> set valMap[" << val << "] to " << valMap[val] << "\n";
}
}
这段代码的预期输出是:
before assignment: valMap.size() = 0 -> set valMap[1] to 0
before assignment: valMap.size() = 1 -> set valMap[3] to 1
before assignment: valMap.size() = 2 -> set valMap[5] to 2
但是,当我使用(默认)C++14 编译器构建发布版本时,输出变为:
before assignment: valMap.size() = 0 -> set valMap[1] to 1
before assignment: valMap.size() = 1 -> set valMap[3] to 2
before assignment: valMap.size() = 2 -> set valMap[5] to 3
换句话说,valMap
中的所有值都比它们应有的值大 1 - 看起来地图是在评估赋值的右侧之前附加的。
这仅发生在使用 C++14 语言标准(这是 VS2019 中的默认设置)的发布版本中。调试版本工作正常(我讨厌这种情况发生——我花了好几个小时才弄清楚发生了什么),C++17 和 C++20 的发布版本也是如此。这就是为什么它对我来说看起来像一个错误。
我的问题是:这是一个编译器错误,还是我在作业中使用 .size()
做了一些 wrong/dangerous?
c++17之前没有指定A = B
的求值顺序,c++17之后B
保证在A
之前求值,见https://en.cppreference.com/w/cpp/language/eval_order 规则 20.
valMap[val] = valMap.size();
的行为因此在 c++14 中未指定,您应该使用:
auto size = valMap.size();
valMap[val] = size;
或者通过使用 emplace
来避免这个问题,这比依靠 []
更明确地自动插入一个值,如果它不存在的话:
valMap.emplace(val, size);
我知道编译器通常是代码中错误的最后一件事,但对于以下 C++ 代码的以下行为(从实际项目中提取),我看不到任何其他解释:
#include <iostream>
#include <map>
int main()
{
auto values = { 1, 3, 5 };
std::map<int, int> valMap;
for (auto const & val : values) {
std::cout << "before assignment: valMap.size() = " << valMap.size();
valMap[val] = valMap.size();
std::cout << " -> set valMap[" << val << "] to " << valMap[val] << "\n";
}
}
这段代码的预期输出是:
before assignment: valMap.size() = 0 -> set valMap[1] to 0
before assignment: valMap.size() = 1 -> set valMap[3] to 1
before assignment: valMap.size() = 2 -> set valMap[5] to 2
但是,当我使用(默认)C++14 编译器构建发布版本时,输出变为:
before assignment: valMap.size() = 0 -> set valMap[1] to 1
before assignment: valMap.size() = 1 -> set valMap[3] to 2
before assignment: valMap.size() = 2 -> set valMap[5] to 3
换句话说,valMap
中的所有值都比它们应有的值大 1 - 看起来地图是在评估赋值的右侧之前附加的。
这仅发生在使用 C++14 语言标准(这是 VS2019 中的默认设置)的发布版本中。调试版本工作正常(我讨厌这种情况发生——我花了好几个小时才弄清楚发生了什么),C++17 和 C++20 的发布版本也是如此。这就是为什么它对我来说看起来像一个错误。
我的问题是:这是一个编译器错误,还是我在作业中使用 .size()
做了一些 wrong/dangerous?
c++17之前没有指定A = B
的求值顺序,c++17之后B
保证在A
之前求值,见https://en.cppreference.com/w/cpp/language/eval_order 规则 20.
valMap[val] = valMap.size();
的行为因此在 c++14 中未指定,您应该使用:
auto size = valMap.size();
valMap[val] = size;
或者通过使用 emplace
来避免这个问题,这比依靠 []
更明确地自动插入一个值,如果它不存在的话:
valMap.emplace(val, size);