当函数涉及重新分配时,我发现一些编译器可能在函数调用之前保存地址。它导致存储在无效地址中的返回值。
在上面的描述中有一个解释行为的例子。
#include <stdio.h>
#include <vector>
using namespace std;
vector<int> A;
int func() {
A.push_back(3);
A.push_back(4);
return 5;
}
int main() {
A.reserve(2);
A.push_back(0);
A.push_back(1);
A[1] = func();
printf("%d\n", A[1]);
return 0;
}
有一些常见的C ++编译器,测试结果如下。
1
5
5
是不确定的行为?
答案 0 :(得分:51)
在C ++ 17之前的所有C ++版本中,行为都是未定义的。原因很简单,可以按任何顺序评估赋值运算符的两边:
A[1]
,那么您将int&
引用A
的第二个元素。func()
,它可以重新分配向量的存储空间,使先前检索的int&
成为悬空引用。 仅在C ++ 17中,分配special rule 20:
在每个简单的赋值表达式中,E1 = E2和每个化合物 赋值表达式E1 @ = E2,每个值计算和副作用 在每个值计算和副作用之前对E2进行排序 E1
使用C ++ 17时,必须在调用A[1]
之后评估func()
,然后set.seed(123)
df <- data.frame(loc.id = rep(1:9, each = 9), month = rep(1:9,times = 9),
x = runif(81, min = 0, max = 5))
提供定义的可靠行为。
答案 1 :(得分:-5)
如果您在“Iterator Invalidation”下检查documentation,您会看到Reimport All Maven Projects
如果更改容量,可能会使每个迭代器无效,因为它必须重新分配记忆。请记住,对于push_back()
,指针也是有效的迭代器。因为std::vector
可能会或可能不会重新分配,并且您无法知道它是否会发生,因此行为未定义。