关于替换不可分配的 vector 元素,存在两个现有问题:

  • C++ Use Unassignable Objects in Vector
  • How to push_back without operator=() for const members?

  • 对象不可分配的典型原因是其类定义包括const成员,因此删除了其operator=
    std::vector要求其元素类型是可分配的。实际上,至少在使用GCC时,当对象不可分配时,直接赋值(vec[i] = x;)或erase()insert()的组合来替换元素都不起作用。

    像下面这样的函数,该函数使用vector::data(),直接元素销毁和复制构造函数中的new放置,可用于替换元素而不引起未定义的行为吗?
    template <typename T>
    inline void replace(std::vector<T> &vec, const size_t pos, const T& src)
    {
      T *p = vec.data() + pos;
      p->~T();
      new (p) T(src);
    }
    

    所用功能的示例如下。这可以在GCC 4.7中进行编译,并且可以正常工作。
    struct A
    {
      const int _i;
      A(const int &i):_i(i) {}
    };
    
    int main() {
      std::vector<A> vec;
      A c1(1);
      A c2(2);
    
      vec.push_back(c1);
      std::cout << vec[0]._i << std::endl;
    
      /* To replace the element in the vector
         we cannot use this: */
      //vec[0] = c2;
    
      /* Nor this: */
      //vec.erase(begin(vec));
      //vec.insert(begin(vec),c2);
    
      /* But this we can: */
      replace(vec,0,c2);
      std::cout << vec[0]._i << std::endl;
    
      return 0;
    }
    

    最佳答案

    这是非法的,因为3.8p7描述了使用析构函数调用和new放置来重新创建对象的方式,它规定了对数据成员类型的限制:



    因此,由于您的对象包含const数据成员,因此在析构函数调用和新放置之后, vector 的内部data指针在用于引用第一个元素时将变得无效;我认为任何明智的解读都会得出结论,同样适用于其他要素。

    这样做的理由是,优化器有权假定const和引用数据成员没有分别被修改或重新定位:

    struct A { const int i; int &j; };
    int foo() {
        int x = 5;
        std::vector<A> v{{4, x}};
        bar(v);                      // opaque
        return v[0].i + v[0].j;      // optimised to `return 9;`
    }
    

    关于c++ - 可以使用placement-new和vector::data()替换 vector 中的元素吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12908398/

    10-11 22:59
    查看更多