我将直接转到代码并解释我在这里想要理解的内容。
class MyInt
{
unique_ptr<int> ptr;
public:
MyInt(int val)
{
cout << __PRETTY_FUNCTION__ << "this: <" << this << ">, val: <" << val << ">" << endl;
ptr = make_unique<int>(val);
}
~MyInt()
{
cout << __PRETTY_FUNCTION__ << "this: <" << this << ">" << endl;
}
MyInt(MyInt&& other) noexcept: ptr(move(other.ptr))
{
cout << __PRETTY_FUNCTION__ << "this: <" << this << ">, other :<" << &other << ">" << endl;
}
MyInt& operator=(MyInt&& other) noexcept
{
cout << __PRETTY_FUNCTION__ << "this: <" << this << ">, other :<" << &other << ">" << endl;
if (this != &other)
{
ptr = move(other.ptr);
other.ptr = nullptr;
}
return *this;
}
};
int main(int argc, char *argv[])
{
MyInt *aptr = new MyInt[2]{11, 22};
for (size_t i = 0; i < 2; ++i)
{
cout << "aptr[" << i << "] :" << &aptr[i] << endl;
}
cout << "deleting :" << endl;
delete [] aptr;
cout << "exiting" << endl;
return 0;
}
这段代码的输出是:
onkar@DESKTOP-MTXXX:~/CppDesignPatterns/build$ ./DesignPatterns/Test
MyInt::MyInt(int)this: <0x7ffe7a274e30>, val: <11>
MyInt::MyInt(MyInt&&)this: <0x7ffe7a274e50>, other :<0x7ffe7a274e30>
MyInt::MyInt(MyInt&&)this: <0x603000000048>, other :<0x7ffe7a274e50>
MyInt::~MyInt()this: <0x7ffe7a274e50>
MyInt::~MyInt()this: <0x7ffe7a274e30>
MyInt::MyInt(int)this: <0x7ffe7a274e70>, val: <22>
MyInt::MyInt(MyInt&&)this: <0x7ffe7a274e90>, other :<0x7ffe7a274e70>
MyInt::MyInt(MyInt&&)this: <0x603000000050>, other :<0x7ffe7a274e90>
MyInt::~MyInt()this: <0x7ffe7a274e90>
MyInt::~MyInt()this: <0x7ffe7a274e70>
aptr[0] :0x603000000048
aptr[1] :0x603000000050
deleting :
MyInt::~MyInt()this: <0x603000000050>
MyInt::~MyInt()this: <0x603000000048>
exiting
onkar@DESKTOP-MTXXX:~/CppDesignPatterns/build$
从上面的代码和输出中,任何人都可以很容易地理解创建临时对象、分配内存并将临时对象移动到数组 aptr 的内存中的适当位置。
我在这里无法理解的是额外的调用 -
MyInt::MyInt(MyInt&&)this: <0x7ffe7a274e50>, other :<0x7ffe7a274e30>
和
MyInt::MyInt(MyInt&&)this: <0x7ffe7a274e90>, other :<0x7ffe7a274e70>
为什么会发生这些电话?目的是什么(或者可能的目的)?
顺便说一句,我传递给 CMake 来构建此代码的标志是
# Set C++ standards
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Disable copy elision, RVO -fno-elide-constructors
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-elide-constructors -g")
即禁用复制省略。
-fno-elide-constructors
删除保证省略。也就是说,对象的创建分几个步骤进行:
Create temporal MyInt (11)
Move MyInt (11) to instance inside of temporal initialization list.
Move MyInt (11) to 1st element of array
Create temporal MyInt (22)
Move MyInt (22) to instance inside of temporal initialization list.
Move MyInt (22) to 2nd element of array
标准行为是在创建数组元素的位置构造数组元素,而不是表达式图的走向:
Create 1st element of array MyInt (11)
Create 2nd element of array MyInt (22)