vector elements allocated on stack? - c++

#include <iostream>
#include <vector>
using namespace std;
struct A {
int i = 0;
};
void append(vector<A>& v) {
auto a = v.back(); // is a allocated on the stack? Will it be cleaned after append() returns?
++a.i;
v.push_back(a);
}
void run() {
vector<A> v{};
v.push_back(A{}); // is A{} created on the stack? Will it be cleaned after run() returns?
append(v);
for (auto& a : v) {
cout << a.i << endl;
}
}
int main() {
run();
return 0;
}
The code above prints as expected:
0
1
But I have two questions:
is A{} created on the stack? Will it be cleaned after run() returns?
is a allocated on the stack? Will it be cleaned after append() returns?
Update:
#include <iostream>
#include <vector>
using namespace std;
struct A {
int i = 0;
A() { cout << "+++Constructor invoked." << endl; }
A(const A& a) { cout << "Copy constructor invoked." << endl; }
A& operator=(const A& a) {
cout << "Copy assignment operator invoked." << endl;
return *this;
};
A(A&& a) { cout << "Move constructor invoked." << endl; }
A& operator=(A&& a) {
cout << "Move assignment operator invoked." << endl;
return *this;
}
~A() { cout << "---Destructor invoked." << endl; }
};
void append(vector<A>& v) {
cout << "before v.back()" << endl;
auto a = v.back();
++a.i;
cout << "before v.push_back()" << endl;
v.push_back(a);
cout << "after v.push_back()" << endl;
}
void run() {
vector<A> v{};
v.push_back(A{});
cout << "entering append" << endl;
append(v);
cout << "exited append" << endl;
for (auto& a : v) {
cout << a.i << endl;
}
}
int main() {
run();
return 0;
}
Output:
+++Constructor invoked.
Move constructor invoked.
---Destructor invoked.
entering append
before v.back()
Copy constructor invoked.
before v.push_back()
Copy constructor invoked.
Copy constructor invoked.
---Destructor invoked.
after v.push_back()
---Destructor invoked.
exited append
0
0 // I understand why it outputs 0 here. I omitted the actual work in my copy/move constructors overloads.
---Destructor invoked.
---Destructor invoked.
I updated the code in my question, adding the copy/move constructors. I found copy constructor was called 3 times in append. I understand auto a = v.back(); needs a copy, But the two other copies maybe should be avoided?

The C++ specification doesn't actually say.
With v.push_back(A{}) the A{} part creates a temporary object, which is then moved or copied into the vector, and then the temporary object is discarded.
Same with local variables, really, the "stack" is actually never mentioned by the C++ standard, it only tells how life-time should be handled. That a compiler might use a "stack" is an implementation detail.
With that said, most C++ compilers will use the "stack" to store local variables. Like for example the variable a in the append function. As for the temporary object created for v.push_back(A{}) you need to check the generated assembly code.
For the life-times, the life-time of the temporary object A{} ends as soon as the push_back function returns. And the life-time of a in the append function ends when the append function returns.

In this function
void append(vector<A>& v) {
auto a = v.back(); // is a allocated on the stack? Will it be cleaned after append() returns?
++a.i;
v.push_back(a);
}
the variable a has the automatic storage duration and is a local variable of the function. It will not be alive after exiting the function.
In this function
void run() {
vector<A> v{};
v.push_back(A{}); // is A{} created on the stack? Will it be cleaned after run() returns?
append(v);
for (auto& a : v) {
cout << a.i << endl;
}
}
again the variable v has the automatic storage duration and is a local variable of the function. When the function will finish its execution the variable will be destroyed. And all elements of the vector (that are placed in the heap) also will be destroyed due to the destructor of the vector.
Consider the following demonstrative program.
#include <iostream>
#include <vector>
struct A {
int i = 0;
};
int main()
{
std::vector<A> v;
std::cout << "&v = " << &v << "\n\n";
A a;
std::cout << "&a = " << &a << "\n\n";
v.push_back( a );
std::cout << "&v = " << &v << '\n';
std::cout << "&a = " << &a << '\n';
std::cout << "&v[0] = " << &v[0] << "\n\n";
++a.i;
v.push_back( a );
std::cout << "&v = " << &v << '\n';
std::cout << "&a = " << &a << '\n';
std::cout << "&v[0] = " << &v[0] << '\n';
std::cout << "&v[1] = " << &v[1] << "\n\n";
return 0;
}
Its output might look like
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v[0] = 0x55725232ee80
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v[0] = 0x55725232eea0
&v[1] = 0x55725232eea4
As you can see the addresses of the vector v and the object a looks similarly because they are allocated in the same outer block scope of the function and have the automatic storage duration.
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
And they are not changed when new values are pushed on the vector.
However the addresses of the elements of the vector as for example
&v[0] = 0x55725232ee80
&v[0] = 0x55725232eea0
&v[1] = 0x55725232eea4
have a different representation and can be changed when a new elements are added to the vector because the memory for them can be dynamically reallocated.
EDIT: After you updated your question then take into account that when a new element is added to the vector the elements of the vector can be reallocated calling the copy constructor. You can use the method reserve to reserve enough memory to avoid its reallocation and the method emplace_back.

is a allocated on the stack?
There is no such thing as "stack" storage in the language. a has automatic storage.
As far as language implementations are concerned, this typically means that the variable is probably stored in a register, or on stack, or nowhere.
Will it be cleaned after append() returns?
Yes. Automatic variables are destroyed automatically when they go out of scope.
is A{} created on the stack?
A{} is a temporary object. The language is a bit vague about the storage class of temporary objects, but it is clear about the lifetime.
Will it be cleaned after run() returns?
In this case, the temporary object is destroyed at the end of the full expression, which is before run returns.
vector elements allocated on stack?
No. Vector elements are created in dynamic storage.
Update
But the two other copies maybe should be avoided?
If your endgoal is to get a vector with two elements, you can avoid all of the copies like this:
std::vector<A> v(2);

Related

Trying to create object using constructor inside static function in C++

I was trying to create an object inside static function using a constructor.
Here is the code
class A {
public:
A() { this->a = 50; std::cout << "constructor called... " << this << std::endl; setAddr(this); }
~A() { this->a = 10; std::cout << "destructor called... " << this << std::endl; }
int a;
static A* addr;
static void setAddr(A* ad) { addr = ad; }
static A &create() { A(); return *addr; }
};
A* A::addr = NULL;
int main() {
A &ptr = A::create();
std::cout << "a = " << ptr.a << std::endl;
ptr.a = 100;
std::cout << "a = " << ptr.a << std::endl;
getch();
return 0;
}
I know using new is best way to do it,but i was trying to do it using contructor to know whether it can be done or not.
The output was:
constructor called... 009AF874
destructor called... 009AF874
a = 10
a = 100
Now here is my question,
1) why destructor is called when did not create an object using any declaration like A obj;
2) and if the destructor is called then how I am able to assign a value to otr.a;
By looking at the program's output I made the following conclusion.
1) I read somewhere that constructor is called after the memory has been allocated to object. And if an object is created then it has to be destroyed and the scope of the obj decided to destroy it now.
2) Since object address has previous values before destroying it and returns call return the address of the variable storing it. When I try to access it, I was able to do so because that memory address still exists.
That's not how you make a singleton. The statement
A();
creates a temporal object of class A that is destroyed (as per standard) at end of statement.
Indeed, memory is allocated before call of constructor. Resulting object can be assigned or passed by reference or value to any function of this statement, but in former case, reference is valid only until end of call expression. Exception is that if it was assigned to reference, its length of life is extended to one
of reference. After life of object ended, any access to memory it used results in UB, provided that it could be used by any other operations.
Any access to object after destructor was called is an UB as well.
Here is an example (this code intentionally contains UB)
#include <iostream>
class A {
public:
A() { this->a = 50; std::cout << "constructor called... " << this << std::endl; }
~A() { this->a = 10; std::cout << "destructor called... " << this << std::endl; }
int a;
static const A &create() {
const A& addr = A();
std::cout << "a = " << addr.a << std::endl;
return addr;
}
};
int main() {
const A &ref = A::create();
std::cout << "a = " << ref.a << std::endl;
return 0;
}
Note, that C++ allows to bind temporary only to const reference. There are way to work around that, but that's irrelevant.
Output of this program may vary, depending on compiler and level of optimization. E.g. clang with no optimization:
constructor called... 0x7ffc1f7991d0
a = 50
destructor called... 0x7ffc1f7991d0
a = 4202884
gcc may output 10 in last line. MS may crash on it. Keyword is "may", there is no rule that governs what would happen. Object stopped existing after create() returned reference to it because lifespan of addr came to end, and we are left with dangling reference.
Obviously we can extend lifespan of addr by making it static.
static const A &create() {
static const A& addr = A();
std::cout << "a = " << addr.a << std::endl;
return addr;
}
Static variable in function's scope will be created at first call of function and stops to exist when process stops.
constructor called... 0x6031b8
a = 50
a = 50
destructor called... 0x6031b8

Delete array of classes without calling destructors

Consider we create the array using this way:
T* arr = new T[num];
And now because of some reasons we understood that we need simply delete that array but without calling any T destructors.
We all know that if we write next:
delete arr;
the T destructor will be called.
If we write this:
delete[] arr;
the num destructors would be called.
Having played with pointers, you realize that new inserts before the result pointer the unsigned long long value that represents the number of allocated T instances. So we try to outwit the C++ trying to change that value to number of bytes that arr occupies and delete it as (char*) in hope that in this case the delete would not call the destructors for T instances and simply free occupied memory. So you write something like this:
typedef unsigned long long;
unsll & num = *(unsll)((char*)arr-sizeof(unsll));
num = num*sizeof(T);
delete ((char*)arr);
But that doesn't work and C++ creates the trigger breakpoint(run time error) when trying to delete this. So that doesn't work. And a lot of other playing with pointers doesn't work as at least some error(compile- or run-time) occurs. So the question is:
Is that possible to delete an array of classes in C++ without calling their destructors?
Perhaps you want ::operator delete[](arr).
(See http://en.cppreference.com/w/cpp/memory/new/operator_delete)
But this still has undefined behaviour, and is a terrible idea.
One simple way to deallocate without calling destructors is to separate allocation and initialization. When you take proper care of alignment you can use placement new (or the functionality of a standard allocator object) to create the object instances inside the allocated block. Then at the end you can just deallocate the block, using the appropriate deallocation function.
I can't think of any situation where this would be a smart thing to do: it smells strongly of premature optimization and X/Y-problem (dealing with problem X by imagining impractical Y as a solution, then asking only about Y).
A new-expression is designed to couple allocation with initialization, so that they're executed as an all-or-nothing operation. This coupling, and ditto coupling for cleanup and deallocation, is key to correctness, and it also simplifies things a lot (i.e., inside there's complexity that one doesn't have to deal with). Uncoupling needs to have a very good reason. Avoiding destructor calls, for e.g. purposes of optimization, is not a good reason.
I'm only going to address your specific question of
Is that possible to delete an array of classes in C++ without calling their destructors?
The short answer is yes.
The long answer is yes, but there's caveats and considering specifically what a destructor is for (i.e. resource clean up), it's generally a bad idea to avoid calling a class destructor.
Before I continue the answer, it should be noted that this is specifically to answer your question and if you're using C++ (vs. straight C), using this code will work (since it's compliant), but if you're needing to produce code in this way, you might need to rethink some of your design since code like this can lead to bugs/errors and general undefined behavior if not used properly.
TL;DR if you need to avoid destructors, you need to rethink your design (i.e. use copy/move semantics or an STL container instead).
You can use malloc and free to avoid constructor and destructor calls, example code:
#include <iostream>
#include <cstdio>
class MyClass {
public:
MyClass() : m_val(0)
{
this->init(42);
std::cout << "ctor" << std::endl;
}
~MyClass()
{
std::cout << "dtor" << std::endl;
}
friend std::ostream& operator<<(std::ostream& stream, const MyClass& val)
{
stream << val.m_val;
return stream;
}
void init(int val)
{
/* just showing that the this pointer is valid and can
reference private members regardless of new or malloc */
this->_init(val);
}
private:
int m_val;
void _init(int val)
{
this->m_val = val;
}
};
template < typename Iterator >
void print(Iterator begin, Iterator end)
{
while (begin != end) {
std::cout << *begin << std::endl;
++begin;
}
}
void set(MyClass* arr, std::size_t count)
{
for (; count > 0; --count) {
arr[count-1].init(count);
}
}
int main(int argc, char* argv[])
{
std::cout << "Calling new[10], 10 ctors called" << std::endl;
MyClass* arr = new MyClass[10]; // 10 ctors called;
std::cout << "0: " << *arr << std::endl;
set(arr, 10);
print(arr, arr+10);
std::cout << "0: " << *arr << std::endl;
std::cout << "Calling delete[], 10 dtors called" << std::endl;
delete[] arr; // 10 dtors called;
std::cout << "Calling malloc(sizeof*10), 0 ctors called" << std::endl;
arr = static_cast<MyClass*>(std::malloc(sizeof(MyClass)*10)); // no ctors
std::cout << "0: " << *arr << std::endl;
set(arr, 10);
print(arr, arr+10);
std::cout << "0: " << *arr << std::endl;
std::cout << "Calling free(), 0 dtors called" << std::endl;
free(arr); // no dtors
return 0;
}
It should be noted that mixing new with free and/or malloc with delete results in undefined behavoir, so calling MyClass* arr = new MyClass[10]; and then call free(arr); might not work as "expected" (hence the UB).
Another issue that will arise from not calling a constructor/destructor in C++ is with inheritance. The above code will work with malloc and free for basic classes, but if you start to throw in more complex types, or inherit from other classes, the constructors/destructors of the inherited classes will not get called and things get ugly real quick, example:
#include <iostream>
#include <cstdio>
class Base {
public:
Base() : m_val(42)
{
std::cout << "Base()" << std::endl;
}
virtual ~Base()
{
std::cout << "~Base" << std::endl;
}
friend std::ostream& operator<<(std::ostream& stream, const Base& val)
{
stream << val.m_val;
return stream;
}
protected:
Base(int val) : m_val(val)
{
std::cout << "Base(" << val << ")" << std::endl;
}
void _init(int val)
{
this->m_val = val;
}
int m_val;
};
class Child : public virtual Base {
public:
Child() : Base(42)
{
std::cout << "Child()" << std::endl;
}
~Child()
{
std::cout << "~Child" << std::endl;
}
void init(int val)
{
this->_init(val);
}
};
template < typename Iterator >
void print(Iterator begin, Iterator end)
{
while (begin != end) {
std::cout << *begin << std::endl;
++begin;
}
}
void set(Child* arr, std::size_t count)
{
for (; count > 0; --count) {
arr[count-1].init(count);
}
}
int main(int argc, char* argv[])
{
std::cout << "Calling new[10], 20 ctors called" << std::endl;
Child* arr = new Child[10]; // 20 ctors called;
// will print the first element because of Base::operator<<
std::cout << "0: " << *arr << std::endl;
set(arr, 10);
print(arr, arr+10);
std::cout << "0: " << *arr << std::endl;
std::cout << "Calling delete[], 20 dtors called" << std::endl;
delete[] arr; // 20 dtors called;
std::cout << "Calling malloc(sizeof*10), 0 ctors called" << std::endl;
arr = static_cast<Child*>(std::malloc(sizeof(Child)*10)); // no ctors
std::cout << "The next line will seg-fault" << std::endl;
// Segfault because the base pointers were never initialized
std::cout << "0: " << *arr << std::endl; // segfault
set(arr, 10);
print(arr, arr+10);
std::cout << "0: " << *arr << std::endl;
std::cout << "Calling free(), 0 dtors called" << std::endl;
free(arr); // no dtors
return 0;
}
The above code is compliant and compiles without error on g++ and Visual Studio, but due to the inheritance, both crash when I try to print the first element after a malloc (because the base class was never initialized).
So you can indeed create and delete an array of objects without calling their constructors and destructors, but doing so results in a slew of extra scenarios you need to be aware of and account for to avoid undefined behavior or crashes, and if this is the case for your code, such that you need to ensure the destructors are not called, you might want to reconsider your overall design (possibly even use an STL container or smart pointer types).
Hope that can help.

Confusion about construction/destruction in vector after std::vector::clear

#include <iostream>
#include <vector>
class A
{
public:
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
};
int main()
{
std::vector<A> myvec;
myvec.push_back(A());
myvec.push_back(A());
myvec.clear();
return 0;
}
output:
constructor
destructor
constructor
destructor
destructor
destructor
destructor
There are five calls to the destructor here. The first two are due to the temporaries which are passed to push_back. There are three other calls, but I expected one two extra calls.
myvec.clear() will clear only two contents so destructor of A should call only two times (instead of three). why there is one extra time destructor is called?
But, if I push_back only one element to the vector, instead of two, the output is as I expected.
The call to std::vector::clear isn't really important in this context because, when myvec goes out of scope, its contents will be destroyed anyway.
Let's consider
class A
{
public:
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
A (const A &) { std::cout << "A(A&)\n"; }
};
int main()
{
std::vector<A> myvec;
std::cout << "First\n";
myvec.push_back(A());
std::cout << "Second\n";
myvec.push_back(A());
std::cout << '\n'; // to separate the final destruction
myvec.clear();
}
which outputs
First
constructor <-- First A _temporary_ object created when pushing_back
A(A&) <-- vector makes a *copy* of the temporary
destructor <-- Temporary A is destroyed
Second
constructor <-- Second A _temporary_ object created when pushing_back
A(A&) <-- Reallocation happens: vector can't copy because it ran out of space
A(A&) <-- Copy of the second temporary
destructor <-- Destroy of the temporary
destructor <-- Destroy of the first element
destructor
destructor
If you std::vector::reserve some space, you can get rid of the copies made by the reallocation
std::vector<A> myvec;
myvec.reserve(8);
which confirms what said
First
constructor
A(A&)
destructor
Second
constructor
A(A&)
destructor
push_back is still making copies of the parameter: this can be further optimized by making your class moveable.
A(A&&) noexcept = default;
A& operator=(A&&) noexcept = default;
First
constructor
destructor
Second
constructor
destructor
This is most likely due to the reallocation that takes place between the first and the second push_back. If you reserve some space ahead of time, then the deallocations are going to be 2 after the two push_backs, as you have expected.
Try this slightly modified version of your program. There is now a copy constructor and an optional reserve (see comment in the program). It will be a lot clearer what is going on.
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A() { cout << " constructor" << endl; }
A(const A & a) { cout << " copy constructor" << endl; }
~A() { cout << " destructor" << endl; }
};
int main()
{
vector<A> myvec;
// myvec.reserve(100); // <<< remove comment to see the difference
cout << "pushback 1" << endl;
myvec.push_back(A());
cout << "pushback 2" << endl;
myvec.push_back(A());
cout << "pushback 3" << endl;
myvec.push_back(A());
cout << "clear" << endl;
myvec.clear();
cout << "end clear" << endl;
return 0;
}

C++ confusion with new and scope

I am trying to learn C++ and from what I've read in books and on SO:
If I use auto x = new Object(); x is a pointer to address of Object and this is in dynamic memory and exists until I delete it.
However if I use Object x; or auto x = Object() it only lasts until it goes out of scope.
In an example they have shown this:
void foo()
{
Point p = Point(0,0);
} // p is now destroyed.
What I don't understand is what happens when I return a object when I don't use new? Will it be a copy of the object?
Here is an example of what I am not sure about:
class Object
{
public:
int X;
static Object Foo(int y)
{
Object result;
result.X = y;
return result;
}
};
class TestContainer
{
public:
void Run()
{
for(auto i = 0; i < 10; i++)
{
_objects.at(i) = Object::Foo(i + (rand() % 10 + 1));
}
}
private:
std::vector<Object> _objects;
};
void main()
{
TestContainer tc;
while(true)
{
tc.Run();
}
}
Note I haven't tested this code but I think it illiterates my confusion. In my main function I instantiate TestContainer and endless call it's Run method. This in turn loops calling a static Foo method on Object that returns a copy of a new Object, which is stored in a vector.
My question is, what happens with all the Object's? If I replace element 2 in the objects vector with a new Object, is the old value now "out of scope" and is deleted?
Will it be a copy of the object?
Yes.
Or a move could be used instead, or the entire thing could be optimised away to produce only one actual object in your final, compiled program.
But, basically, yes.
If I replace element 2 in the objects vector with a new Object, is the old value now "out of scope" and is deleted?
Yes.
As an aside, you're using at on elements that don't exist; to add elements, use insert or push_back.
A simple class like this behaves much like a POD variable. o1=o2 copies the fields, element-wise. So the target Object of an assignment does not get deleted but overwritten.
Objects which go out of scope "go away" (because the stack is unwound) like e.g. an int.
Here is a run-able example that I believe illustrates this behavior:
#include <iostream>
using namespace std;
class Foo {
private:
int id;
public:
Foo(int x)
: id(x)
{
cout << this->id << " is created" << endl;
}
Foo(const Foo& rhs)
: id(rhs.id)
{
cout << "copied " << this->id << endl;
}
Foo& operator=(Foo rhs){
this->id=rhs.id;
cout << "assigned " << this->id << endl;
return *this;
}
~Foo(){
cout << this->id << " is destroyed" << endl;
}
int getID(){
return this->id;
}
};
Foo bar(){
Foo f1 = Foo(1);
cout << f1.getID() << " from bar" << endl;
return f1;
}
int main(){
Foo f2 = bar();
cout << f2.getID() << " from main" << endl;
return 0;
}
This produces this output:
1 is created
1 from bar
1 from main
1 is destroyed
From this, I'm not seeing a copy or an assignment. I suspect what is happening is that both f1 and f2 are referencing the same instance of the object in memory. The object is not being de-allocated when the f1 reference goes out of scope because the object has another reference assigned to it.

Why does vector::push_back and emplace_back call value_type::constructor twice?

I have this class:
class Foo {
public:
Foo() {}
Foo(const Foo&){cout << "constructed by lvalue reference." <<endl; }
Foo(Foo&& ) {cout << "constructed by rvalue reference." << endl; }
};
then I insert into a vector:
Foo foo{};
vf.push_back(foo);
The output is surprising:
constructed by lvalue reference.
constructed by lvalue reference.
I assume it got copied when passing parameters, so I tried:
vf.push_back(move(foo));
and
vf.push_back(forward<Foo>(foo));
The output are slightly different due to move semantics but still calling constructor twice:
constructed by rvalue reference.
constructed by lvalue reference.
Why the constructors got called twice? How much performance does it impact? How can I avoid this?
I am using mingw-gcc-4.7.1 on Windows Vista
Total example:
#include <iostream>
#include <vector>
using namespace std;
class Foo {
public:
Foo() {}
Foo(const Foo&){cout << "constructed by lvalue reference." <<endl; }
Foo(Foo&& ) {cout << "constructed by rvalue reference." << endl; }
};
int main(int argc, char **argv, char** envp)
{
vector<Foo> vf;
cout << "Insert a temporary." << endl;
vf.emplace_back(Foo{});
Foo foo{};
cout << "Insert a variable." << endl;
vf.emplace_back(foo);
return 0;
}
Exact output:
Insert a temporary.
constructed by rvalue reference.
Insert a variable.
constructed by lvalue reference.
constructed by lvalue reference.
When you insert new items in a vector the vector may have to allocate more memory to fit those objects. When that happens it needs to copy all it's elements to the new memory location. That will invoke the copy constructor. So when you insert your element you're getting the constructor for that new element and the constructor when copying the previous element.
vector<Foo> vf;
cout << "Insert a temporary." << endl;
vf.emplace_back(Foo{});
What happens above is that a temporary Foo is created.
This temporary is then used to construct a Foo within the vector. So a "constructed by rvalue reference" is what you asked for.
If you wish to simply construct the Foo in place, try:
vs.emplace_back();
Next:
Foo foo{};
cout << "Insert a variable." << endl;
vf.emplace_back(foo);
here you construct a non-temporary foo. You then instruct the std::vector to construct a new element at the end of the list.
The interesting thing is that you get two construct by lvalue reference. The second seems to be caused by the resize. Why the resize causes you to be construced by lvalue reference, instead of rvalue reference, is a trick: if your move constructor is not marked noexcept, std::vector falls back on copy instead of move!
Here is a live example illustrating the above principles:
#include <iostream>
#include <vector>
using namespace std;
class Foo {
public:
Foo() {}
virtual ~Foo() {}
Foo(const Foo&){cout << "constructed by lvalue reference." <<endl; }
Foo(Foo&){cout << "constructed by non-const lvalue reference." <<endl; }
Foo(Foo&& ) noexcept {cout << "constructed by rvalue reference." << endl; }
};
int main(int argc, char **argv, char** envp)
{
vector<Foo> vf;
cout << "Insert a temporary. One move:" << endl;
vf.emplace_back(Foo{});
cout << "Insert a temporary(2). Two moves:" << endl;
vf.emplace_back(Foo{});
cout << "Resize with temporary(3). Two moves:" << endl;
vf.resize(10);
vector<Foo> vf2;
Foo foo{};
cout << "Insert a variable. One copy:" << endl;
vf2.emplace_back(foo);
cout << "Insert a variable(2). One move, one copy:" << endl;
vf2.emplace_back(foo);
cout << "Resize with variable(3). Two moves:" << endl;
vf2.resize(10);
vector<Foo> vf3;
cout << "Insert a nothing. No copy or move:" << endl;
vf3.emplace_back();
cout << "Insert a nothing(2). One move:" << endl;
vf3.emplace_back();
cout << "Resize with nothing(3). Two moves:" << endl;
vf3.resize(10);
}
A common implementation of std::vector::push_back looks like this:
void push_back(value_type _Val)
{ // insert element at end
insert_n(size(), 1, _Val);
}
As you can see, the input parameter is passed-by-value (so it is copied) in both the push_back declaration and the insert_n declaration. Hence, the copy-constructor is called twice.
After cleaning up your syntax:
#include <iostream>
#include <vector>
using namespace std;
class Foo
{
public:
Foo() {}
Foo(const Foo&) {cout << "constructed by lvalue reference." <<endl; }
Foo(Foo&&) {cout << "constructed by rvalue reference." << endl; }
};
int main()
{
vector<Foo> vf;
cout << "Size = " << vf.size() << endl;
cout << "Capacity = " << vf.capacity() << endl;
cout << "Insert a temporary" << endl;
vf.push_back(Foo()); // this is still very discouraged syntax
Foo foo;
cout << "Insert a variable." << endl;
vf.push_back(foo);
return 0;
}
You get the following output:
Size = 0
Capacity = 0
Insert a temporary
constructed by rvalue reference.
Insert a variable.
constructed by rvalue reference.
constructed by lvalue reference.
Press any key to continue . . .
In this example, I'm using a standard version of std::vector (which passes by const-reference or by reference-to-reference). The initial push_back call creates a capacity of 1 (and a size of 1). The 2nd call creates a new block of memory, moves the first item, and copies the second (the newly added) item.
In terms of performance, you aren't going to take a big hit for small reallocations. There are a few different common memory models used (the one with Visual Studio grows your capacity exponentially each time it has to grow to decrease the need for it in the future). If you know you will be starting with 100 elements, you should reserve space when you create your vector so allocation only happens once, which will also prevent the need to move existing elements when inserting new elements (due to the fact that you won't be exceeding your capacity multiple times).