Hi I created a class Foo with a noexcept move constructor using gcc 4.7 and set the vector reserve size to 2 so that it would have to reallocate the size when adding the 3rd item. It seems it is calling the copy constructor instead of the move constructor when doing this. Am I missing something here?
#include <vector>
#include <iostream>
class Foo
{
public:
Foo(int x) : data_(x)
{
std::cout << " constructing " << std::endl;
}
~Foo()
{
std::cout << " destructing " << std::endl;
}
Foo& operator=(const Foo&) = default;
Foo& operator=(Foo&&) = default;
Foo(Foo&& other) noexcept : data_(std::move(other.data_))
{
std::cout << " Move constructing " << std::endl;
}
Foo(const Foo& other) noexcept : data_(other.data_)
{
std::cout << " Copy constructing " << std::endl;
}
private:
int data_;
};
int main ( int argc, char *argv[])
{
std::vector<Foo> v;
v.reserve(2);
v.emplace_back(1);
std::cout << "Added 1" << std::endl;
v.emplace_back(2);
std::cout << "Added 2" << std::endl;
v.emplace_back(3);
std::cout << "Added 3" << std::endl;
std::cout << "v size: " << v.size() << std::endl;
}
output:
constructing
Added 1
constructing
Added 2
constructing
Copy constructing
Copy constructing
destructing
destructing
Added 3
v size: 3
destructing
destructing
destructing
No. It doesn't call the move constructor. To call move constructor of element you will have to call std::move while pushing to vector itself.
The push_back method is used to append an element in a sequential STL container (e.g., std::vector). When inserted using the push_back, the new element is copy-or-move-constructed.
The default copy constructor will copy all members – i.e. call their respective copy constructors. So yes, a std::vector (being nothing special as far as C++ is concerned) will be duly copied.
The move constructor is much faster than a copy constructor because it doesn't allocate memory nor does it copy memory buffers.
After tinkering with it a bit with both GCC 4.7 and 4.8, it seems that it is indeed a bug in 4.7, which only appears when the class' destructor is not marked noexcept
:
struct Foo {
Foo() {}
~Foo() noexcept {}
Foo(Foo&&) noexcept { std::cout << "move constructor" << std::endl; }
Foo(const Foo&) noexcept { std::cout << "copy constructor" << std::endl; }
};
int main() {
std::vector<Foo> v;
v.reserve(2);
v.emplace_back();
v.emplace_back();
v.emplace_back();
}
GCC 4.7 displays:
move constructor
move constructor
If we remove noexcept
from the destructor:
struct Foo {
Foo() {}
~Foo() {}
Foo(Foo&&) noexcept { std::cout << "move constructor" << std::endl; }
Foo(const Foo&) noexcept { std::cout << "copy constructor" << std::endl; }
};
GCC 4.7 displays:
copy constructor
copy constructor
GCC 4.8 uses the move constructor in both cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With