对于以下类别的大小为 5 的 vector ,
struct Aclass
{
double x;
std::vector<double> y;
Aclass(){}
Aclass(double x, int ysize): x(x)
{
y.resize(ysize, x * ysize);
}
};
我想删除第二个元素:
void eraseEle()
{
std::vector<Aclass> v(5, Aclass(1, 3));
// Erase the 2nd element
{
std::vector<double>(0).swap(v[2].y);
// Copy the bits from &v[3] ~ &v[5] to &v[2]:
std::memmove(&v[2], &v[3], sizeof(Aclass) * (v.size() - 3));
v.resize(v.size() - 1);
}
// Print
for(int i = 0, iend = v.size(); i < iend; ++i)
{
std::cout << v[i].x << ", " << v[i].y[0] << "\n";
}
}
方法很不规范。 g++ 4.9.3 -O2
编译它,但程序总是在 std::memmove(...)
处崩溃。是否因为 STL vector 的 header 以某种方式受到保护导致 std::memmove()
触发未定义的行为?
谢谢!
更深入的回答:
未定义行为的原因是 .resize()
释放了 v[4]
中的容器,所以之后,v[3]
包含一个指向任何内容的 vector
header ,在访问 vector 元素时引发未定义的行为。要真正让它发挥作用,请添加
std::fill((char*)(&v.back().y), (char*)(&v.back().y) + 24, 0);
在 v.resize(v.size() - 1); 之前
。上面的代码通过让最后一个元素(要删除的)包含一个指向任何内容的 vector
来防止 .resize()
释放容器内存。
最佳答案
reference在 memmove
上声明:
If the objects are not TriviallyCopyable, the behavior of memmove is not specified and may be undefined
并且 STL vector 对象不是普通可复制对象。
正如一条评论中所建议的那样, vector 成员函数 erase
执行您想要执行的操作。
Trivially-copyable对象是类的对象,其中:
- Every copy constructor is trivial or deleted
- Every move constructor is trivial or deleted
- Every copy assignment operator is trivial or deleted
- Every move assignment operator is trivial or deleted
- at least one copy constructor, move constructor, copy assignment operator, or move assignment operator is non-deleted
- Trivial non-deleted destructor
This implies that the class has no virtual functions or virtual base classes.
Scalar types and arrays of TriviallyCopyable objects are TriviallyCopyable as well, as well as the const-qualified (but not volatile-qualified) versions of such types.
关于c++ - 复制具有 STL vector 类型成员的类的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52713288/