push_back vs emplace_back

后端 未结 7 2293
南旧
南旧 2020-11-22 03:41

I\'m a bit confused regarding the difference between push_back and emplace_back.

void emplace_back(Type&& _Val);
void push_         


        
相关标签:
7条回答
  • 2020-11-22 03:45

    emplace_back shouldn't take an argument of type vector::value_type, but instead variadic arguments that are forwarded to the constructor of the appended item.

    template <class... Args> void emplace_back(Args&&... args); 
    

    It is possible to pass a value_type which will be forwarded to the copy constructor.

    Because it forwards the arguments, this means that if you don't have rvalue, this still means that the container will store a "copied" copy, not a moved copy.

     std::vector<std::string> vec;
     vec.emplace_back(std::string("Hello")); // moves
     std::string s;
     vec.emplace_back(s); //copies
    

    But the above should be identical to what push_back does. It is probably rather meant for use cases like:

     std::vector<std::pair<std::string, std::string> > vec;
     vec.emplace_back(std::string("Hello"), std::string("world")); 
     // should end up invoking this constructor:
     //template<class U, class V> pair(U&& x, V&& y);
     //without making any copies of the strings
    
    0 讨论(0)
  • 2020-11-22 03:48

    emplace_back conforming implementation will forward arguments to the vector<Object>::value_typeconstructor when added to the vector. I recall Visual Studio didn't support variadic templates, but with variadic templates will be supported in Visual Studio 2013 RC, so I guess a conforming signature will be added.

    With emplace_back, if you forward the arguments directly to vector<Object>::value_type constructor, you don't need a type to be movable or copyable for emplace_back function, strictly speaking. In the vector<NonCopyableNonMovableObject> case, this is not useful, since vector<Object>::value_type needs a copyable or movable type to grow.

    But note that this could be useful for std::map<Key, NonCopyableNonMovableObject>, since once you allocate an entry in the map, it doesn't need to be moved or copied ever anymore, unlike with vector, meaning that you can use std::map effectively with a mapped type that is neither copyable nor movable.

    0 讨论(0)
  • 2020-11-22 03:49

    A nice code for the push_back and emplace_back is shown here.

    http://en.cppreference.com/w/cpp/container/vector/emplace_back

    You can see the move operation on push_back and not on emplace_back.

    0 讨论(0)
  • 2020-11-22 03:56

    Specific use case for emplace_back: If you need to create a temporary object which will then be pushed into a container, use emplace_back instead of push_back. It will create the object in-place within the container.

    Notes:

    1. push_back in the above case will create a temporary object and move it into the container. However, in-place construction used for emplace_back would be more performant than constructing and then moving the object (which generally involves some copying).
    2. In general, you can use emplace_back instead of push_back in all the cases without much issue. (See exceptions)
    0 讨论(0)
  • 2020-11-22 04:00

    One more in case of lists:

    // constructs the elements in place.                                                
    emplace_back("element");
    
    
    //It will create new object and then copy(or move) its value of arguments.
    push_back(explicitDataType{"element"});
    
    0 讨论(0)
  • 2020-11-22 04:07

    Optimization for emplace_back can be demonstrated in next example.

    For emplace_back constructor A (int x_arg) will be called. And for push_back A (int x_arg) is called first and move A (A &&rhs) is called afterwards.

    Of course, the constructor has to be marked as explicit, but for current example is good to remove explicitness.

    #include <iostream>
    #include <vector>
    class A
    {
    public:
      A (int x_arg) : x (x_arg) { std::cout << "A (x_arg)\n"; }
      A () { x = 0; std::cout << "A ()\n"; }
      A (const A &rhs) noexcept { x = rhs.x; std::cout << "A (A &)\n"; }
      A (A &&rhs) noexcept { x = rhs.x; std::cout << "A (A &&)\n"; }
    
    private:
      int x;
    };
    
    int main ()
    {
      {
        std::vector<A> a;
        std::cout << "call emplace_back:\n";
        a.emplace_back (0);
      }
      {
        std::vector<A> a;
        std::cout << "call push_back:\n";
        a.push_back (1);
      }
      return 0;
    }
    

    output:

    call emplace_back:
    A (x_arg)
    
    call push_back:
    A (x_arg)
    A (A &&)
    
    0 讨论(0)
提交回复
热议问题