unique_ptr 与原始指针的不同行为
Different behaviour of unique_ptr vs raw pointer
我正在努力理解原始指针和 unique_ptr 的行为差异。我有 class A
和变量 x
和 class B
以及指向 A
:
实例的指针
class A
{
public:
int x;
};
A::A(int y) : x(y)
{
}
class B
{
public:
B(A &);
A *p;
};
B::B(A &a)
{
p = &a;
}
这符合我的预期:
int main()
{
A a(2);
B b(a);
cout << a.x << " " << b.p->x << endl;
a.x = 4;
cout << a.x << " " << b.p->x << endl;
}
给予
2 2
4 4
将原始指针更改为 std::unique_ptr 会得到不同的结果:
class A
{
public:
int x;
};
A::A(int y) : x(y)
{
}
class B
{
public:
B(A &);
std::unique_ptr<A> p;
};
B::B(A &a)
{
p = std::make_unique<A>(a);
}
给予
2 2
4 2
我是否从根本上误解了 unique_ptrs 的某些内容?
make_unique
创建一个新对象,unique_pt
可以独占访问该对象。因此,在第二个示例中,您有两个对象,而不是一个,当您在第一个对象中设置更改 a.x
的值时,它不会影响 unique_ptr
.[=14= 持有的另一个对象]
尝试从智能指针版本读取以下表达式:
std::make_unique<A>(a);
"制作 唯一 A
来自 a
"(没有提到指针!)
结果是unique_ptr
,但是在读取表达式时,将其读取为使(类型为)模板参数。函数参数是构造函数的参数。在这种情况下,您正在从一个 A
对象创建一个 A
对象,它会拉入复制构造函数。
一旦您了解智能指针版本正在创建一个新的 A
对象(而您的原始指针版本则不会),您的结果应该是有意义的。
“唯一A
”中的“唯一”可能很难理解。将其视为一个其他人无法拥有的对象。它可能是另一个对象的副本,但是,作为unique_ptr
的角色,它是你的副本,你的负责清理干净之后,就没有别人的了。你的宝贝,你不会分享的(c.f。std::make_shared
)。
请注意,局部变量(如 main
函数中的 a
)是编译器的责任,因此它没有资格成为 unique_ptr
的对象点(或任何智能指针,就此而言)。
一个独特的指针需要拥有它指向的任何东西。您的代码可以工作 - 只需替换 unique_ptr 类型并保持其他一切不变(没有 make_unique)。但它会有未定义的行为,因为您将创建一个指向其他地方拥有的对象的唯一指针。
为了比较苹果与苹果,原始指针代码应为 p=new A(a);
。这就是 make_unique
所做的。
我正在努力理解原始指针和 unique_ptr 的行为差异。我有 class A
和变量 x
和 class B
以及指向 A
:
class A
{
public:
int x;
};
A::A(int y) : x(y)
{
}
class B
{
public:
B(A &);
A *p;
};
B::B(A &a)
{
p = &a;
}
这符合我的预期:
int main()
{
A a(2);
B b(a);
cout << a.x << " " << b.p->x << endl;
a.x = 4;
cout << a.x << " " << b.p->x << endl;
}
给予
2 2
4 4
将原始指针更改为 std::unique_ptr 会得到不同的结果:
class A
{
public:
int x;
};
A::A(int y) : x(y)
{
}
class B
{
public:
B(A &);
std::unique_ptr<A> p;
};
B::B(A &a)
{
p = std::make_unique<A>(a);
}
给予
2 2
4 2
我是否从根本上误解了 unique_ptrs 的某些内容?
make_unique
创建一个新对象,unique_pt
可以独占访问该对象。因此,在第二个示例中,您有两个对象,而不是一个,当您在第一个对象中设置更改 a.x
的值时,它不会影响 unique_ptr
.[=14= 持有的另一个对象]
尝试从智能指针版本读取以下表达式:
std::make_unique<A>(a);
"制作 唯一 A
来自 a
"(没有提到指针!)
结果是unique_ptr
,但是在读取表达式时,将其读取为使(类型为)模板参数。函数参数是构造函数的参数。在这种情况下,您正在从一个 A
对象创建一个 A
对象,它会拉入复制构造函数。
一旦您了解智能指针版本正在创建一个新的 A
对象(而您的原始指针版本则不会),您的结果应该是有意义的。
“唯一A
”中的“唯一”可能很难理解。将其视为一个其他人无法拥有的对象。它可能是另一个对象的副本,但是,作为unique_ptr
的角色,它是你的副本,你的负责清理干净之后,就没有别人的了。你的宝贝,你不会分享的(c.f。std::make_shared
)。
请注意,局部变量(如 main
函数中的 a
)是编译器的责任,因此它没有资格成为 unique_ptr
的对象点(或任何智能指针,就此而言)。
一个独特的指针需要拥有它指向的任何东西。您的代码可以工作 - 只需替换 unique_ptr 类型并保持其他一切不变(没有 make_unique)。但它会有未定义的行为,因为您将创建一个指向其他地方拥有的对象的唯一指针。
为了比较苹果与苹果,原始指针代码应为 p=new A(a);
。这就是 make_unique
所做的。