简体   繁体   English

std :: vector :: assign - 重新分配数据?

[英]std::vector::assign - reallocates the data?

I am working with STL library and my goal is to minimize the data reallocation cases. 我正在使用STL库,我的目标是最小化数据重新分配的情况。 I was wndering, does 我在想,是吗?

std::vector::assign(size_type n, const value_type& val) std :: vector :: assign(size_type n,const value_type&val)

reallocated the data if the size is not changed or does is actually just assign the new values (for example, using operator=) ? 如果大小未更改或者实际上只是分配新值(例如,使用operator =),则重新分配数据?

The STL documentation at http://www.cplusplus.com/ sais the following (C++98): http://www.cplusplus.com/上的STL文档sais如下(C ++ 98):

In the fill version (2), the new contents are n elements, each initialized to a copy of val. 在填充版本(2)中,新内容是n个元素,每个元素都初始化为val的副本。 If a reallocation happens,the storage needed is allocated using the internal allocator. 如果发生重新分配,则使用内部分配器分配所需的存储。

Any elements held in the container before the call are destroyed and replaced by newly constructed elements (no assignments of elements take place). 在调用之前容器中保存的任何元素都被销毁并被新构造的元素替换(不会发生元素的赋值)。 This causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity. 如果 - 并且仅当新的矢量大小超过当前矢量容量时,这将导致分配的存储空间的自动重新分配。

The phrase "no assignments of elements take place" make it all a little confusing. 短语“没有元素的分配发生”使得这一切都有点令人困惑。

So for example, I want to have a vector of classes (for example, cv::Vec3i of OpenCV). 所以例如,我想要一个类的向量(例如,OpenCV的cv :: Vec3i)。 Does this mean, that 这是否意味着,那

  1. the destructor or constructor of cv::Vec3i will be called? 将调用cv :: Vec3i的析构函数或构造函数?
  2. a direct copy of Vec3i memory will be made and fills the vector? 将制作Vec3i内存的直接副本并填充向量?
  3. what happens, if my class allocates memory at run time with new operator? 如果我的类在运行时使用new运算符分配内存会发生什么? This memory cannot be accounted for by plain memory copying. 普通内存复制无法解释此内存。 Does it mean, that assign() should not be used for such objects? 这是不是意味着,assign()不应该用于这样的对象?

EDIT: the whole purpose of using assign in this case is to set all values in the vector to 0 (in case I have std::vector< cv::Vec3i > v). 编辑:在这种情况下使用assign的全部目的是将向量中的所有值设置为0(如果我有std :: vector <cv :: Vec3i> v)。 It will be done many-many times. 它会做很多次。 The size of std::vector itself will not be changed. std :: vector本身的大小不会改变。

what i want to do (in a shorter way) is the following: 我想做什么(以较短的方式)是以下内容:

 for(int i=0; i<v.size(); i++)  
   for(int j=0; j<3; j++)
     v[i][j] = 0;

right now I am interested in C++98 现在我对C ++ 98感兴趣

std::vector.assign(...) does not reallocate the vector if it does not have to grow it. 如果不需要增长它, std::vector.assign(...)不会重新分配该向量。 Still, it must copy the actual element. 但是,它必须复制实际元素。

If you want to know what the standard guarantees, look in the standard: C++11 standard plus minor editorial changes. 如果您想知道标准保证什么,请查看标准: C ++ 11标准以及次要的编辑更改。

I assume that you have a vector filled with some data and you call an assign on it, this will: 我假设你有一个载有一些数据的向量,你在它上面调用一个赋值,这将:

  1. destroy all the elements of the vector (their destructor is called) like a call to clear() 销毁向量的所有元素(它们的析构函数被调用)就像调用clear()
  2. fill the now-empty vector with n copies of the given object, which must have a copy constructor. 使用给定对象的n个副本填充now-empty向量,该副本必须具有复制构造函数。

So if your class allocates some memory you have to: 因此,如果您的类分配了一些内存,您必须:

  1. take care of this in your copy constructor 在你的拷贝构造函数中处理这个问题
  2. free it in the destructor 在析构函数中释放它

Reallocations happen when the size exceed the allocated memory (vector capacity). 当大小超过分配的内存(向量容量)时,会发生重新分配。 You can prevent this with a call to reserve(). 您可以通过调用reserve()来阻止这种情况。 However I think that assign() is smart enough to allocate all the memory it needs (if this is more than the already allocated) before starting to fill the vector and after having cleared it. 但是我认为assign()足够聪明,可以在开始填充向量之前和清除之后分配所需的所有内存(如果这比已经分配的内存多)。

You may want to avoid reallocations because of their cost, but if you are trying to avoid them because your objects cannot handle properly, then I strongly discourage you to put them in a vector. 您可能希望避免重新分配,因为它们的成本,但如果您试图避免它们因为您的对象无法正常处理,那么我强烈建议您不要将它们放在向量中。

The semantics of assign are defined the standard in a quite straightforward way: assign的语义以一种非常直接的方式定义为标准:

void assign(size_type n, const T& t); void assign(size_type n,const T&t);

Effects: 功效:

erase(begin(), end());
insert(begin(), n, t);

This means that first the destructors of the elements will be called. 这意味着首先将调用元素的析构函数。 The copies of t are made in what is now a raw storage left after the lifetime of the elements ended. t的副本是在元素结束的生命周期之后留下的原始存储中创建的。

The requirements are that value_type is MoveAssignable (for when erase doesn't erase to the end of the container and needs to move elements towards the beginning). 要求是value_typeMoveAssignable (当erase不擦除到容器的末尾并且需要将元素移动到开头时)。

insert overload used here requires that value_type is CopyInsertable and CopyAssignable. 这里使用的insert重载要求value_typeCopyInsertableCopyAssignable.

In any case, vector is oblivious to how your class is managing its own resources. 无论如何,vector无视你的班级如何管理自己的资源。 That's on you to take care of. 这是你要照顾的。 See The Rule of Three. 三法则。

As in the case of vector::resize method, vector::resize方法一样,

std::vector::assign(size_type n, const value_type& val)

will initialize each element to a copy of "val" . 将每个元素初始化为“val”副本 I prefer to use resize as it minimizes the number of object instanciations/destructions, but it does the same. 我更喜欢使用resize因为它最大限度地减少了对象实例/破坏的数量,但它也是如此。 Use resize if you want to minimize the data realloc, but keep in mind the following: 如果要最小化数据realloc,请使用resize ,但请记住以下内容:

While doing this is safe for certain data structures, be aware that assigning /pushing elements of a class containing pointers to dynamically allocated data (eg with a new in the constructor) may cause havoc. 虽然这样做对某些数据结构是安全的,但要注意,分配/推送包含指向动态分配数据的指针的类的元素(例如,在构造函数中使用new )可能会造成严重破坏。

If your class dynamically allocates data then you should reimplement the YourClass::operator= to copy the data to the new object instead of copying the pointer. 如果您的类动态分配数据,那么您应该重新实现YourClass::operator=以将数据复制到新对象而不是复制指针。

Hope that it helps! 希望它有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM