Reputation: 1360
I'm practicing C++ move semantics code with above code, but MemoryBlock
's move constructor for value 25
is called twice.
After that, MemoryBlock
s destructor is called twice in a row.
Here's the code:
#include <iostream>
#include <vector>
class MemoryBlock {
private:
int length;
int* data;
public:
// Default constructor
MemoryBlock() = default;
// Constructor
explicit MemoryBlock(int p_length) : length(p_length), data(new int[length]) {
std::cout << "In MemoryBlock(int), length is " << length << ".\n";
}
// Destructor
~MemoryBlock() {
std::cout << "~MemoryBlock() is called. Deleting resources.\n";
delete[] data;
}
// Copy constructor
MemoryBlock(const MemoryBlock& other) : length(other.length), data(new int[other.length]) {
std::cout << "In MemoryBlock(const MemoryBlock&), length is " << length << ".\n";
for (int i = 0; i < length; ++i) {
data[i] = other.data[i];
}
}
// Move constructor
MemoryBlock(MemoryBlock&& other) noexcept : length(0), data(nullptr) {
std::cout << "In MemoryBlock(MemoryBlock&&), length is " << other.length << ".\n";
length = other.length;
data = other.data;
other.length = 0;
other.data = nullptr;
}
};
int main() {
std::vector<MemoryBlock> vec;
vec.push_back(MemoryBlock(25)); // (1)
vec.push_back(MemoryBlock(60)); // (2)
std::cout << "----------------- End of main() -----------------\n";
return 0;
}
RESULT:
In MemoryBlock(int), length is 25. // #1: Generate temporary object
In MemoryBlock(MemoryBlock&&), length is 25. // Move temporary object #1 to vec's node
~MemoryBlock() is called. Deleting resources. // Destruct temporary object #1
In MemoryBlock(int), length is 60. // #2: Generate temporary object
In MemoryBlock(MemoryBlock&&), length is 60. // Move temporary object #2 to vec's node
In MemoryBlock(MemoryBlock&&), length is 25. // ??
~MemoryBlock() is called. Deleting resources. // ??
~MemoryBlock() is called. Deleting resources. // ??
----------------- End of main() -----------------
~MemoryBlock() is called. Deleting resources. // Destruct vec's node 60
~MemoryBlock() is called. Deleting resources. // Destruct vec's node 25
I want to know why the line marked with ??
is called.
Upvotes: 1
Views: 80
Reputation: 2380
Initially Vector in your code has zero capacity. Its Allocator
is allocating memory for one object at push_back
.
After vec.push_back(MemoryBlock(60)); // (2)
new chunk of memory for 2 elements is allocated and first element is moved to new memory chunk.
use vec.reserve(2);
to avoid this.
Upvotes: 3
Reputation: 1535
It seems std::vector uses some reallocating internally. This is the debugger output just before second "In MemoryBlock(MemoryBlock&&), length is 25." is called.
#0 MemoryBlock::MemoryBlock (this=0x419410, other=...) at memblock.cc:44
#1 0x0000000000401bba in __gnu_cxx::new_allocator<MemoryBlock>::construct<MemoryBlock, MemoryBlock> (this=0x7fffffffd6d0, __p=0x419410, __args#0=...) at /usr/include/c++/9/ext/new_allocator.h:147
#2 0x0000000000401819 in std::allocator_traits<std::allocator<MemoryBlock> >::construct<MemoryBlock, MemoryBlock> (__a=..., __p=0x419410, __args#0=...)
at /usr/include/c++/9/bits/alloc_traits.h:484
#3 0x0000000000402267 in std::__relocate_object_a<MemoryBlock, MemoryBlock, std::allocator<MemoryBlock> > (__dest=0x419410, __orig=0x4192f0, __alloc=...)
at /usr/include/c++/9/bits/stl_uninitialized.h:894
#4 0x000000000040216d in std::__relocate_a_1<MemoryBlock*, MemoryBlock*, std::allocator<MemoryBlock> > (__first=0x4192f0, __last=0x419300, __result=0x419410, __alloc=...)
at /usr/include/c++/9/bits/stl_uninitialized.h:932
#5 0x0000000000402056 in std::__relocate_a<MemoryBlock*, MemoryBlock*, std::allocator<MemoryBlock> > (__first=0x4192f0, __last=0x419300, __result=0x419410, __alloc=...)
at /usr/include/c++/9/bits/stl_uninitialized.h:946
#6 0x0000000000401ef2 in std::vector<MemoryBlock, std::allocator<MemoryBlock> >::_S_do_relocate (__first=0x4192f0, __last=0x419300, __result=0x419410, __alloc=...)
at /usr/include/c++/9/bits/stl_vector.h:453
#7 0x0000000000401d73 in std::vector<MemoryBlock, std::allocator<MemoryBlock> >::_S_relocate (__first=0x4192f0, __last=0x419300, __result=0x419410, __alloc=...)
at /usr/include/c++/9/bits/stl_vector.h:466
#8 0x000000000040195e in std::vector<MemoryBlock, std::allocator<MemoryBlock> >::_M_realloc_insert<MemoryBlock> (this=0x7fffffffd6d0, __position={length = 0, data = 0x101}, __args#0=...)
at /usr/include/c++/9/bits/vector.tcc:461
#9 0x000000000040176e in std::vector<MemoryBlock, std::allocator<MemoryBlock> >::emplace_back<MemoryBlock> (this=0x7fffffffd6d0, __args#0=...) at /usr/include/c++/9/bits/vector.tcc:121
#10 0x0000000000401606 in std::vector<MemoryBlock, std::allocator<MemoryBlock> >::push_back (this=0x7fffffffd6d0, __x=...) at /usr/include/c++/9/bits/stl_vector.h:1201
#11 0x000000000040128f in main () at memblock.cc:58
Upvotes: 3