移动构造函数的意外调用

Unintended call of move constructor

本文关键字:调用 意外 构造函数 移动      更新时间:2023-10-16

我正在练习C++上面的代码移动语义代码,但是MemoryBlock的值25的移动构造函数被调用了两次。 之后,连续调用两次MemoryBlock析构函数。

代码如下:

#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;
}

(现场试用(

结果:

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

我想知道为什么标有??的行被调用。

最初代码中的 Vector 容量为零。它Allocator是在push_back时为一个对象分配内存。

vec.push_back(MemoryBlock(60)); // (2)为2个元素分配新的内存块后,第一个元素被移动到新的内存块。

使用vec.reserve(2);来避免这种情况。

似乎 std::vector 在内部使用了一些重新分配。这是在调用第二个"In MemoryBlock(MemoryBlock&&(,长度为 25">之前的调试器输出。

#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