可视化C++将分配移动到未初始化的对象?



作为后续: 使用复制构造函数后双重释放子对象

我按照建议遵循了 5 法则。 但是现在似乎移动分配发生在未初始化的对象上(对象 ID 为 0(?我希望它从对象 3 移动到对象 2。

我创建了以下(最小?(示例,该示例似乎触发了我的问题:

#include <stdio.h>
#include <stdint.h>
class A
{
public:
A()
{
myCtr = ++ctr;
printf("class A default Constructor - object id: %un", myCtr);
}
A(const A &a2) {
myCtr = ++ctr;
printf("class A copy constructor - object id: %un", myCtr);
}
A(A &&a2) {
myCtr = a2.myCtr;
a2.myCtr = 0;
printf("class A move constructor - object id: %un", myCtr);
}
A & operator=(const A &a2) {
myCtr = ++ctr;
printf("class A copy assignment - from object id: %u - to object id: %un", a2.myCtr, myCtr);
return *this;
}
A & operator=(A &&a2) {
printf("class A move assignment - from object id: %u - to object id: %un", a2.myCtr, myCtr);
if (this != &a2) {
//myCtr = a2.myCtr;
//a2.myCtr = 0;
}
return *this;
}
~A()
{
printf("class A destructor - object id: %un", myCtr);
}
private:
uint64_t myCtr;
static uint64_t ctr;
};
class B
{
public:
B() {
}
B(char * input, uint32_t len) {
for (uint32_t i = 0; i < len; i++)
{
/* do something */
}
}
B(const B &b2) {
characters = A(b2.characters);
}
B(B &&b2) {
characters = A(b2.characters);
}
B & operator=(const B &b2) {
characters = A(b2.characters);
}
B & operator=(B &&b2) {
characters = A(b2.characters);
}
~B() {
}

private:
A characters;
};
uint64_t A::ctr = 0;
int main(int argc, char *argv[]) {
B b1 = B((char *)"b1", 2);
B b2 = b1;
return 0;
}

这将生成以下输出:

class A default Constructor - object id: 1
class A default Constructor - object id: 2
class A copy constructor - object id: 3
class A move assignment - from object id: 3 - to object id: 0
class A destructor - object id: 3
class A destructor - object id: 2
class A destructor - object id: 1

这是我没想到的台词:

class A move assignment - from object id: 3 - to object id: 0

期望:

class A move assignment - from object id: 3 - to object id: 2

我正在使用以下编译器:Microsoft (R( C/C++ 优化编译器版本 19.14.26429.4

万一你投反对票。请具体说明原因。我很乐意尝试改进我的问题。

编辑:

似乎只有面向 x86 平台的 Visual C++ 编译器才会出现此问题。它适用于g++(x86和x64(,clang(x86和x64(和msvc(x64(。这使得我更难弄清楚这个问题的根源。

在构造函数中

B(const B &b2) {
characters = A(b2.characters);
}

首先创建类型 A 的临时对象,然后将其移动到characters变量。这就是移动分配发生的原因。

尝试将此构造函数替换为:

B(const B &b2) : characters(b2.characters)
{   
}

你会得到你预测的结果(https://ideone.com/yqvINu,VS示例:http://rextester.com/PTPZKR93068(。

最新更新