在std :: vector中调整大小与push_back:它是否避免了不必要的复制赋值?

Chu*_*uim 22 c++ stl vector

push_back从中调用方法时std::vector,其大小增加1,意味着创建新实例,然后您传递的参数将被复制到最近创建的元素中,对吧?例:

myVector.push_back(MyVectorElement());
Run Code Online (Sandbox Code Playgroud)

那么,如果我想简单地使用其默认值来增加向量的大小,那么使用该resize方法会不会更好?我的意思是这样的:

myVector.resize(myVector.size() + 1);
Run Code Online (Sandbox Code Playgroud)

据我所知,这将完成相同的事情,但会避免完全不必要的元素属性的赋值副本.

这种推理是正确的还是我错过了什么?

Yac*_*oby 19

至少对于GCC来说,使用哪个并不重要(结果如下).但是,如果你不得不担心它,你应该使用指针或(甚至更好)某种形式的智能指针..我当然会推荐boost库中的那些.

如果你想知道这是更好地在实践中使用,我建议要么push_backreserve作为调整大小每次调用,除非它的大小与所要求的大小同时将调整向量.push_back和保留只会在需要时调整矢量大小.这是一件好事,好像你想要调整矢量大小size+1,它可能已经存在size+20,所以调用大小调整不会带来任何好处.

测试代码

#include <iostream>
#include <vector>

class Elem{
    public:
        Elem(){
            std::cout << "Construct\n";
        }
        Elem(const Elem& e){
            std::cout << "Copy\n";
        }
        ~Elem(){
            std::cout << "Destruct\n";
        }   
};


int main(int argc, char* argv[]){
    {
        std::cout << "1\n";
        std::vector<Elem> v;
        v.push_back(Elem());
    }

    {
        std::cout << "\n2\n";
        std::vector<Elem> v;
        v.resize(v.size()+1);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试输出

1
Construct
Copy
Destruct
Destruct

2
Construct
Copy
Destruct
Destruct
Run Code Online (Sandbox Code Playgroud)


GMa*_*ckG 16

我发现myVector.push_back(MyVectorElement());更直接,更容易阅读.

问题是,resize不只是调整那些地方的数组和默认构造元素; 这就是它默认的内容.它实际上需要第二个参数,即每个新元素的副本,默认为T().实质上,您的两个代码示例完全相同.

  • @Martin York:当然,使用`resize`来增加大小可能会触发底层数组的实际"大小调整"以及新元素的实例化.但我几乎可以肯定,每次都不会改变底层数组的大小; 只有在需要的时候. (2认同)

And*_*nck 6

在EA(电子艺界)这被认为是他们写自己的STL,版本这么大的问题EASTL,这在许多其他事情包括push_back(void)在他们的vector课.


raf*_*fak 6

关于Yacobi接受的答案测试代码的c ++ 0x观点:

  1. 在类中添加一个移动构造函数:

    Elem(Elem&& e) { std::cout << "Move\n"; }
    
    Run Code Online (Sandbox Code Playgroud)

    使用gcc我得到"移动"而不是"复制"作为输出push_back,这一般来说效率更高.

  2. 使用emplace操作稍微好一点 (使用与构造函数相同的参数):

    v.emplace_back()

测试输出:

1
Construct
Destruct

2
Construct
Copy
Destruct
Destruct
Run Code Online (Sandbox Code Playgroud)