gpt4 book ai didi

c++ - 可以使用placement-new 和vector::data() 替换 vector 中的元素吗?

转载 作者:IT老高 更新时间:2023-10-28 22:14:06 27 4
gpt4 key购买 nike

关于替换不可赋值的 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 来重新创建对象,指定了对数据成员类型的限制:

3.8 Object lifetime [basic.life]

7 - If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object [...] can be used to manipulate the new object, if: [...]
— the type of the original object [...] does not contain any non-static data member whose type is const-qualified or a reference type [...]

因此,由于您的对象包含一个 const 数据成员,在析构函数调用和放置 new 之后, 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com