重新排序不相关的指令改变了结果
reordering of unrelated instructions changed the result
我有一些代码,其中一些指令是相互独立的(它们不相互影响)。但是当我重新排列它们时,它们的语义(意思)就改变了。就像他们互相影响一样。我不明白为什么。
可疑指令为multigraph->push_back(...)
(见代码中的标记)。
我看到两种可能性。要么我不知道它们是如何连接的,要么编译器做错了。
我没有发现任何类似的stackoverflow(也许我使用错误的关键字)。
请告诉我为什么会这样。
您将看到下面的代码。我期望在检查了边[0 3]之后,顶点0的度数为0,即edge [0 3]
→ vertex 0 is a leaf
-degrees: {0:0} ...
下面是代码(我只提取了重要的部分)。
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef vector<pair<int, int> >::iterator edgeIt;
vector<pair<int, int> >* some_fun() {
vector<pair<int, int> >* result = new vector<pair<int, int> >();
result->push_back(make_pair(0, 3));
result->push_back(make_pair(1, 2));
result->push_back(make_pair(1, 4));
result->push_back(make_pair(2, 5));
result->push_back(make_pair(3, 5));
result->push_back(make_pair(3, 8));
result->push_back(make_pair(5, 6));
result->push_back(make_pair(6, 7));
return result;
}
const int n = 9;
int degree[n];
int main() {
vector<pair<int, int> >* multigraph = some_fun();
sort(multigraph->begin(), multigraph->end());
/// vertices' degrees
int degree[n];
for (int i=0 ; i<n ; degree[i++]=0);
for (edgeIt it=multigraph->begin() ; it!=multigraph->end() ; it++){
degree[it->first]++;
degree[it->second]++;
}
cerr << " degrees: ";
for (int i=0 ; i<n ; i++)
cerr << "{" << i << ":" << degree[i] << "} ";
cerr << endl;
/// double edges for leaves
vector<int> leaves;
int mstSize = multigraph->size();
for (int i=0 ; i<mstSize ; i++) {
pair<int, int>* el = &(*multigraph)[i];
cerr << " edge [" << el->first << " " << el->second << "] n";
if (degree[el->first]==1) {
cerr << " → vertex " << el->first << " is a leaf n";
// here it will not work
// multigraph->push_back(make_pair(el->first, el->second));
degree[el->first]=0;
degree[el->second]++;
// but here it's OK
multigraph->push_back(make_pair(el->first, el->second));
leaves.push_back(el->first);
}
else if (degree[el->second]==1) {
cerr << " →→ vertex " << el->second << " is a leaf n";
degree[el->first]++;
degree[el->second]=0;
multigraph->push_back(make_pair(el->first, el->second));
leaves.push_back(el->second);
}
cerr << "t -degrees: ";
for (int i=0 ; i<n ; i++)
cerr << "{" << i << ":" << degree[i] << "} ";
cerr << endl;
}
cerr << " *leaves: ";
for (int i=0 ; i<leaves.size() ; ++i)
cerr << leaves[i] << " ";
cerr << endl;
delete multigraph;
return 0;
}
我找到了罪魁祸首。
如果向量变大会怎样?它可以重新分配它的内容,这样el
将不再指向向量的第i个元素,它将指向内存中某个意义未知的位置。
指令
pair<int, int>* el = &(*multigraph)[i];
是危险的。它接受vector容器中元素的地址。push_back
指令触发重新分配,因此在之后调用el->first
不再正确。
在对矢量进行更改之前,从el
下读取值可以修复此问题。
相关文章:
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 变量没有改变?通过向量的函数调用
- C++:对不存在的命名空间使用命名空间指令
- 函数名是c中该函数的第一条指令的地址吗
- 如何改变c++应用程序的视觉效果
- C++在不同线程中改变向量
- 如何访问和改变存储在矢量C++中的对象
- 错误:无效的预处理指令 #i 的意思是 #if?
- 组装指令中乘法的下部和上部是什么
- 在C++行尾写一个分号或多个分号是否会改变任何内容
- 为什么字符串的 move() 会改变内存中底层数据的位置?
- OpenMP 与有序和关键指令并行
- 为什么 c++ 动态数组的大小没有改变?
- C++中的移动分配出现问题.非法指令: 4.
- 为什么提升图库的 read_graphviz() 函数会改变节点的索引
- 嵌套命名空间的"using"指令,但需要命名内部命名空间
- 在向量内更改变量的值不会改变其在向量外的值
- 为什么改变这些指令的顺序会显著影响性能
- 重新排序不相关的指令改变了结果