-3

When I run this code:

#include <iostream>
#include <vector>
#include <memory>

struct X {
    X() { std::cout << "X()" << std::endl; }
    X(const X&) { std::cout << " X(const X&)" << std::endl; }
    X& operator=(const X& orig) {
        std::cout << " X& operator=" << std::endl;
    }
    ~X() { std::cout <<"~X()" << std::endl; }
};
int main(int argc, char const *argv[])
{
    std::vector<X> vec;
    for (int i = 0; i < 3; ++ i) {
        vec.push_back(X());
        std::cout << "==========" << std::endl;
        vec.emplace_back(X());
        std::cout << "**********" << std::endl;
    }
    return 0;
}

The output is:

the output1

the output2

I don't know why it would be like this. What is the difference between push_back() and emplace_back()? How does the vector allocate the memory?

Remy Lebeau
  • 505,946
  • 29
  • 409
  • 696
Ustinian
  • 15
  • 2
  • 4
    Please don't create screenshorts and images of text. Copy-paste text *as text* into your question. – Some programmer dude Jan 21 '22 at 15:29
  • 1
    A lot of those invocations of the copy constructor come from the vector resizing as you insert elements into it. Whenever you want to add a new element to a vector and it's at capacity, it has to copy or move all the existing elements. You don't have a noexcept move constructor (because you declared your own copy constructor and didn't provide a move constructor) so `std::vector` performs copies. – Nathan Pierson Jan 21 '22 at 15:31
  • One of the reasons for the output is that `std::vector` allocates memory piece-wise. It begins by allocating space for one object, which it moves or copies into the vector. Then when you add the second element the vector needs to be resized so it allocate space for two element and *copies* the first element to the new memory. And so on. – Some programmer dude Jan 21 '22 at 15:31
  • some part of the answer can be found eg here https://en.cppreference.com/w/cpp/container/vector. And you should make the question more focused by stating which output in particular you do not understand or what you expected instead – 463035818_is_not_a_number Jan 21 '22 at 15:35
  • You can also set a reserved size for the `vector` as constructor argument or with the `reserve()` function – Sebastian Jan 21 '22 at 15:38
  • 1
    [Why not upload images of code/errors when asking a question?](https://meta.stackoverflow.com/q/285551/995714) – phuclv Jan 21 '22 at 15:40
  • `vec.emplace_back(X())` should be just `vec.emplace_back()` no need to construct a temporary `X`, like with `push_back()`. – Remy Lebeau Jan 21 '22 at 15:53

1 Answers1

0

Apart from the answers given in the comments (which I encourage you to follow up), you're not supposed to pass an already constructed object to emplace_back - that obviates the whole point of it, which is to construct an object in place.

Instead, you should pass the parameters to be passed to your constructor, which in your case is none, so you want:

vec.emplace_back();

and when you do that, you get:

...
==========
X()
**********
...

which, I believe, is what you were looking for.

Live demo

Paul Sanders
  • 21,574
  • 4
  • 24
  • 46