std::vector - emplace_back

Apr 13, 2020 at 4:28am
I am trying to better understand construction, moving and copying objects.

To test when each operation is happening I have created the following struct:
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <vector>

struct Object
{
	Object() { std::cout << "Constructed" << std::endl; }
	Object(const Object& object) { std::cout << "Copied" << std::endl; }
	Object(Object&&) noexcept { std::cout << "Moved" << std::endl; }
	~Object() { std::cout << "Destroyed" << std::endl; }
};


1. I was told the following would prevent an unnecessary copy:
1
2
3
4
5
6
7
8
int main()
{
	std::vector<Object> objects;

	Object obj;
        // Do stuff with obj..
	objects.emplace_back(obj);
}


However according to my tests to standard out, this is definitely making a copy, the output is:
Constructed
Copied
Destroyed
Destroyed


They said it was the same as writing objects.push_back(std::move(obj)), either I'm missing something or this is incorrect, the only way to replicate that with emplace_back for me was to write objects.emplace_back(std::move(obj)) which will now output "Moved" instead.

2. Even if I were to use std::move(obj) and have the object moved, what benefit does this provide? I still seem to have two instances as I can access the original obj, and I get two calls to the destructor.

I think I've managed to just really confuse myself :)
Last edited on Apr 13, 2020 at 4:28am
Apr 13, 2020 at 5:06am
https://en.cppreference.com/w/cpp/container/vector/emplace_back
objects.emplace_back(Object());
Constructs and inserts the element at the end. No need to pre-construct the object as you would do with push_back.
Last edited on Apr 13, 2020 at 5:47pm
Apr 13, 2020 at 5:20am
Without addressing moves, forwarding, and the mechanisms behind these features:

objects.push_back(obj) is identical to objects.emplace_back(obj): both make copies; and
objects.push_back(std::move(obj)) is identical to objects.emplace_back(std::move(obj)); both move from obj (if there's a move constructor available).

The difference is that emplace_back takes any number of arguments to be passed to the element's constructor:
1
2
3
4
struct A: Object { A(int, int) {}; };
// ... 
std::vector<A> xs;
xs.emplace_back(2, 3);


Constructs an A in-place inside the container: no copies or moves are required.
Last edited on Apr 13, 2020 at 5:20am
Apr 13, 2020 at 5:21am
...
Last edited on Apr 13, 2020 at 5:33am
Apr 13, 2020 at 5:27am
Thanks for the reply.

Woudn't objects.emplace_back(Object); trigger a compiler error? I think it would just be objects.emplace_back() if you wanted to use the default constructor.

My confusion is specifically with what I've been told regarding the examples given with the move/copy semantics. They have pretty much said objects.push_back(std::move(obj)) is equivalent to objects.emplace_back(obj) however I don't believe that is correct, and my second question is what is the benefit (if there is one) of using std::move in this situation.
Apr 13, 2020 at 7:23am
Thanks mbozzi, I really should refresh the page before posting replies lol.

This is what I came to understand, however I was told (by one of my teachers) what I mentioned in my question which I thought was wrong. I wasn't really in a position to question them though lol. Thank you for clearing that up.

I would like to start learning about the underlying mechanisms of moves and forwarding, I will start researching it but if anyone has a particular reference to recommend I wouldn't say no ;)

Apr 13, 2020 at 5:49pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <vector>

struct Object
{
	Object() { std::cout << "Constructed" << std::endl; }
	Object(const Object& object) { std::cout << "Copied" << std::endl; }
	Object(Object&&) noexcept { std::cout << "Moved" << std::endl; }
	~Object() { std::cout << "Destroyed" << std::endl; }
};

int main()
{
	std::vector<Object> obj;

	obj.emplace_back(Object());

	system("pause");
}

Constructed
Moved
Destroyed
Press any key to continue . . .
Destroyed

Topic archived. No new replies allowed.