唯一指针与原始指针

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 的内存,您不需要显式释放内存。