唯一指针与原始指针
unique pointer vs raw pointer
试图理解 unique_pointer 与原始指针访问
#include <iostream>
#include <memory>
int main() {
int a = 10;
int *x = &a;
int *y = &a;
std::unique_ptr<int> p1 = std::make_unique<int>(a);
std::cout<<*x<<*p1<<*y<<"\n";
// prints 101010
*p1 = 20;
std::cout<<*x<<*p1<<*y<<"\n";
// prints 102010
*x =30;
std::cout<<*x<<*p1<<*y<<"\n";
// 302030
return 0;
}
输出
101010
102010
302030
Program ended with exit code: 0
上面代码中x,y,p1都是指向变量a;
所以值 a 的变化应该反映到所有取消引用的指针。
请帮助我理解行为,我是现在从使用原始指针转向智能指针的少数人。
你错了,p1
没有指向 a
。
而是 std::make_unique<int>(a)
创建一个全新的 int
对象并将其初始化为 a
的当前 值。
要使 p1
指向 a
你需要做
std::unique_ptr<int> p1(&a);
然而,这会带来其他问题,例如 p1
接管 &a
的 所有权 ,并在 [=11] 时尝试释放该内存=] 被破坏(这是不可能的)。
您可以使用 the Boost null_deleter
来避免最后一个问题。
但我建议,在大多数情况下,您不应将智能指针视为简单的自删除指针,而应从所有权的角度来看。
以下代码基于MSVC。
原因
std::make_unique()
让你创建新的对象,而不是引用参数
你可以发现unique_ptr p1
得到了不同的地址
int a = 10; // &a = 0x000000bd7d5dfb74
int* x = &a; // x = 0x000000bd7d5dfb74
int* y = &a; // y = 0x000000bd7d5dfb74
std::unique_ptr<int> p1 = std::make_unique<int>(a); // p1._Mypair._Myval2 = 0x00000288fbbd6ba0
std::cout << *x << *y << *p1 << "\n";
*p1 = 20;
std::cout << *x << *y << *p1 << "\n";
*x = 30;
std::cout << *x << *y << *p1 << "\n";
解决方案
如Some programmer dude
所说,使用std::unique_ptr<int> p1(&a);
这导致unique_ptr表示相同的地址
int* a = new int(10); // a = 0x0000027411117260
int* x = a; // x = 0x0000027411117260
int* y = a; // y = 0x0000027411117260
std::unique_ptr<int> p1(a); // p1._Mypair._Myval2 = 0x0000027411117260
std::cout << *x << *y << *p1 << "\n";
*p1 = 20;
std::cout << *x << *y << *p1 << "\n";
*x = 30;
std::cout << *x << *y << *p1 << "\n";
仅供参考,因为 unique_ptr p1
将释放 a
的内存,您不需要显式释放内存。
试图理解 unique_pointer 与原始指针访问
#include <iostream>
#include <memory>
int main() {
int a = 10;
int *x = &a;
int *y = &a;
std::unique_ptr<int> p1 = std::make_unique<int>(a);
std::cout<<*x<<*p1<<*y<<"\n";
// prints 101010
*p1 = 20;
std::cout<<*x<<*p1<<*y<<"\n";
// prints 102010
*x =30;
std::cout<<*x<<*p1<<*y<<"\n";
// 302030
return 0;
}
输出
101010
102010
302030
Program ended with exit code: 0
上面代码中x,y,p1都是指向变量a; 所以值 a 的变化应该反映到所有取消引用的指针。
请帮助我理解行为,我是现在从使用原始指针转向智能指针的少数人。
你错了,p1
没有指向 a
。
而是 std::make_unique<int>(a)
创建一个全新的 int
对象并将其初始化为 a
的当前 值。
要使 p1
指向 a
你需要做
std::unique_ptr<int> p1(&a);
然而,这会带来其他问题,例如 p1
接管 &a
的 所有权 ,并在 [=11] 时尝试释放该内存=] 被破坏(这是不可能的)。
您可以使用 the Boost null_deleter
来避免最后一个问题。
但我建议,在大多数情况下,您不应将智能指针视为简单的自删除指针,而应从所有权的角度来看。
以下代码基于MSVC。
原因
std::make_unique()
让你创建新的对象,而不是引用参数你可以发现unique_ptr
p1
得到了不同的地址int a = 10; // &a = 0x000000bd7d5dfb74 int* x = &a; // x = 0x000000bd7d5dfb74 int* y = &a; // y = 0x000000bd7d5dfb74 std::unique_ptr<int> p1 = std::make_unique<int>(a); // p1._Mypair._Myval2 = 0x00000288fbbd6ba0 std::cout << *x << *y << *p1 << "\n"; *p1 = 20; std::cout << *x << *y << *p1 << "\n"; *x = 30; std::cout << *x << *y << *p1 << "\n";
解决方案
如
Some programmer dude
所说,使用std::unique_ptr<int> p1(&a);
这导致unique_ptr表示相同的地址
int* a = new int(10); // a = 0x0000027411117260 int* x = a; // x = 0x0000027411117260 int* y = a; // y = 0x0000027411117260 std::unique_ptr<int> p1(a); // p1._Mypair._Myval2 = 0x0000027411117260 std::cout << *x << *y << *p1 << "\n"; *p1 = 20; std::cout << *x << *y << *p1 << "\n"; *x = 30; std::cout << *x << *y << *p1 << "\n";
仅供参考,因为 unique_ptr
p1
将释放a
的内存,您不需要显式释放内存。