一次,我创建了一个指向std::vector
的指针,然后我对这个向量执行了一些push_back
,reserve
,resize
操作,将指针与该向量的地址进行比较以检查指针是否指向该向量是否安全,因为可能存在一些内存重新分配。
例如
std::vector<int> vec;
vector<int>* pVec = &vec;
vec.reserve(10000);
assert(pVec == &vec);
vec = anotherVec;
assert(pVec == &vec);
更重要的是,将指针与向量的第一个值进行比较是否安全? 例如:
std::vector<int> vec(1,0);
int* p = &vec[0];
// some operation here
assert(p == &vec[0]);
正如我自己测试的那样,第一种情况似乎是安全的,而第二种情况则不然,但我无法确定。
答案 0 :(得分:7)
std::vector<int> vec;
vector<int>* pVec = &vec;
vec.reserve(10000);
assert(pVec == &vec);
是安全的。
std::vector<int> vec(1,0);
int* p = &vec[0];
// some operation here
assert(p == &vec[0]);
不安全。
第一个块是安全的,因为即使内容发生变化,地址vec
也不会改变。
第二个块不安全,因为vec[0]
的地址可能会更改;例如,当vec
调整自身大小时 - 例如,当你将元素推送到它时。
答案 1 :(得分:2)
似乎第一种情况是安全的,而第二种情况不是
那是对的。在第一个&#34;情境&#34;中,vec
对象本身会保留在内存中的任何位置,而不管reserve
调用,这可能会将托管元素移动到另一个动态记忆领域。这是因为可以移动指针在第二种情况下指针可能无法比较的元素。
答案 2 :(得分:2)
第二种情况是安全只要不进行重新安置。如果你事先知道你需要的大小并在获得指针之前使用reserve()
,那么它是非常安全的,你可以节省一点性能(一个较低的间接级别)。
但是,例如push_back()
的任何添加可能超出分配的空间并使指针无效。 std::vector
已经过优化,如果可能的话,会尝试在同一位置分配更多内存(因为它可以节省复制数据),但你无法确定。
就此而言,不是采用指针就可以使用迭代器,因为向量上的迭代器的行为与指针完全相同(并且没有性能影响),具有更多的类型安全性。
答案 3 :(得分:1)
vector<int>* pVec = &vec;
对std::vector<int>
对象的地址进行操作,该对象在范围内有效。
vec = anotherVec;
不会更改vec的地址,因为此处operator =
的{{1}}被调用。
因此,std::vector
都成功通过了。
在assert(pVec == &vec);
取决于具体情况:请参阅Iterator invalidation
。
答案 4 :(得分:1)
第一种情况确实是安全的,因为矢量对象的地址没有变化的危险。第二种情况是安全的,只要没有重新分配发生(可以使用std :: vector :: capacity成员函数跟踪重新分配),否则根据语言的版本,它是未定义的或实现定义的。有关详细信息consult this answer.,因为在这种情况下适用相同的限制。