【问题标题】:Is it safe to compare to pointer of std::vector to check equality?与 std::vector 的指针进行比较以检查相等性是否安全?
【发布时间】:2015-08-26 14:20:33
【问题描述】:

一次,我创建了一个指向std::vector 的指针,然后我对该向量进行了一些push_backreserveresize 操作,在这些操作之后,比较指针是否安全该向量的地址以检查指针是否指向该向量,因为可能会重新分配内存。

例如

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]);

根据我自己的测试,第一种情况似乎是安全的,而第二种情况则不是,但我不能确定。

【问题讨论】:

    标签: c++ pointers c++11 vector


    【解决方案1】:
    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 调整自身大小时 - 例如,当您将元素 push_back 时。

    【讨论】:

      【解决方案2】:

      似乎第一种情况是安全的,而第二种情况则不然

      没错。在第一种“情况”中,vec 对象本身保留在内存中的任何位置,而不管reserve 调用如何,这可能会将托管元素移动到动态内存的另一个区域。这是因为元素可以移动,所以在第二种情况下指针可能不相等。

      【讨论】:

        【解决方案3】:

        第二种情况是安全的只要没有搬迁发生。如果您提前知道所需的大小并在获得指针之前使用reserve(),那么它是非常安全的,并且您可以节省一点性能(减少一级间接)。

        但是,任何与 push_back() 的添加都可能超出分配的空间并使您的指针无效。 std::vector 已经过优化,如果可能,会尝试在同一位置分配更多内存(因为它可以节省复制数据),但您不能确定这一点。

        就此而言,您可以使用迭代器代替指针,因为向量上的迭代器的行为与指针完全一样(并且没有性能影响),并且类型安全性更高。

        【讨论】:

          【解决方案4】:

          vector&lt;int&gt;* pVec = &amp;vec;std::vector&lt;int&gt; 对象的地址进行操作,该对象在作用域前有效。 vec = anotherVec; 不会更改 vec 的地址,因为这里调用了 std::vectoroperator =。 所以,assert(pVec == &amp;vec); 都成功通过了。

          int* p = &amp;vec[0]; 的情况下,这取决于:请参阅Iterator invalidation

          【讨论】:

            【解决方案5】:

            第一种情况确实是安全的,因为不存在向量对象地址改变的危险。只要不发生重新分配,第二种情况是安全的(可以使用 std::vector::capacity 成员函数跟踪重新分配),否则它是未定义的或实现定义的,具体取决于语言的版本。有关更多信息consult this answer.,因为在这种情况下适用相同的限制。

            【讨论】:

              猜你喜欢
              • 2020-11-19
              • 1970-01-01
              • 2021-09-16
              • 2015-03-13
              • 2017-04-09
              • 1970-01-01
              • 2014-06-17
              • 2016-08-10
              相关资源
              最近更新 更多