关于替换不可分配的 vector 元素,存在两个现有问题:
对象不可分配的典型原因是其类定义包括
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/