等效于智能指针中的指针

Equivalent of pointer in smart pointers

提问人:Novice_Developer 提问时间:11/15/2023 最后编辑:Remy LebeauNovice_Developer 更新时间:11/16/2023 访问量:117

问:

我是指针的新手,所以请考虑以下代码:

#include <iostream>
#include <memory>

int main()
{
    double xNormal{5};
    double * pNormal = &xNormal;
    xNormal = 10;
    std::cout<<"value of variable we are pointing to is : "<<*pNormal<<std::endl;
        
    double xSmart{5};
    std::unique_ptr<double> pSmart = std::make_unique<double>(xSmart);
    xSmart = 10;
    std::cout<<"value of variable we are pointing to through a smart pointer is : "<<*pSmart<<std::endl;
}

此代码的输出为:

value of variable we are pointing to is : 10
value of variable we are pointing to through a smart pointer is : 5

在此代码中,如果我们使用普通指针并更改原始变量的值,则取消引用的指针也会“跟踪”该值,因为它指向该内存位置。

当谈到智能指针时,我注意到没有这样的“跟踪”,也许我在理解上犯了错误,但问题是,智能指针中的等价物是什么?double * pNormal = &xNormal;

C++ 指针 Smart-Pointers

评论

0赞 Pete Becker 11/15/2023
这并不能解决问题,但此代码中的任何内容都不需要额外的内容。 结束一行。std::endl'\n'
1赞 Eljay 11/15/2023
此代码似乎与智能指针的功能背道而驰。你可以做......但是,当被破坏时,你会遇到问题,因为它实际上并不拥有底层(自动存储范围拥有它)。在被摧毁之前,它需要这样做。std::unique_ptr<double> pSmart(&xSmart);pSmartxSmartpSmart.release()
0赞 Peter 11/15/2023
错误地期望创建直接管理(或引用或指向)的智能指针。创建的智能点管理一个(动态分配),该智能点与 不同,但被初始化为具有与 相同的值。去掉智能指针的使用,你的代码就可以有效地执行了。在我的版本中,比较地址,它们将具有不同的值std::make_unique<double>(xSmart)xSmartdoublexSmartxSmartdouble xSmart{5}; double * pSmart = new double{xSmart}; xSmart = 10; std::cout << *pSmart; delete pSmart;&xSmartpSmart
3赞 molbdnilo 11/15/2023
我个人认为,最好不要将“智能指针”视为指针,而是将其视为对所有权有特殊想法的对象。
0赞 Pepijn Kramer 11/15/2023
它仍然要分配一个值,从这个意义上说,用法与原始指针没有什么不同。但正如@molbdnilo所说,你描述了意图。使用 std::unique_ptr 时,您说指针只有一个所有者(稍后需要释放内存的代码)。*pSmart = 10;

答:

3赞 Michael Chourdakis 11/15/2023 #1
std::unique_ptr<double> pSmart = std::make_unique<double>(xSmart);

此行创建一个指针,其中包含调用时的值。它不会创建指向现有变量的指针。xSmart

不想使用 .std::unique_ptr::reset()

std::unique_ptr<bar> pointer;
pointer.reset(&xSmart);

如何将现有对象的地址分配给智能指针?

因为它会破坏一些局部的东西,正如提到的答案所说。您不想要或绕过自动(堆叠)对象。deletestd::unique_ptrstd::shared_ptr

评论

0赞 Michael Chourdakis 11/15/2023
如果我比你的评论多 5 秒,我会添加这个。
2赞 Jarod42 11/15/2023
“你需要。”不,因为正如您提到的,它会做一个无效的.如果你提供 hack,请提供所有东西,但最好不要提供 hack。std::unique_ptr::resetdeleterelease()
1赞 Andrej Podzimek 11/16/2023 #2

有什么作用:std::make_unique<double>(xSmart)

  1. 分配堆内存并为其分配给定,就像调用 一样。sizeof(double)new double{xSmart}
  2. 返回指向新内存的指向。智能指针在其析构函数中,一旦超出范围,就会分配内存。std::unique_ptr<double>delete
  3. 因此,a 永远不应该指向堆内存,就像 一样,因为它稍后尝试 a 会导致崩溃和/或任意未定义的行为。std::unique_ptrstd::unique_ptr<double>{&xSmart}delete

总之,指针中没有引用。的值 from 已复制到新的、动态分配的 .以下是一些好有坏的例子。xSmartpSmartxSmartdouble

  1. 只是一个风格建议/意见:更喜欢引用而不是指针,这些指针总是指向存在的东西,即不应该持有.nullptr
  2. 不要在家尝试这个。在文档中,您可以发现自定义类可以提供给 .这就是我们在这里所做的。删除程序不执行任何操作。这样一来,你就可以构造一个“智能”(实际上是愚蠢的)指针,它指向堆位置,并且不会造成严重破坏。毋庸置疑,这充其量是完全无用和令人困惑的。Deleterstd::unique_ptr
  3. 这大致基于您的动态、智能指针大小写。首先,我们动态分配并分配给它。然后,我们采用一个老式的指针指向 .然后我们通过指针分配它,并检查指向的位置(在堆上)是否真的发生了变化。是的,它做到了。这次我们使用 ,即模板的默认值,即 end 和 析构函数运行时分配的堆内存。double5doublestd::default_delete<double>Deleterdeletemain()pUselessSmart
#include <iostream>
#include <memory>

int main() {
  // Example 0: A local reference to a double on the stack.
  double xNormal{5};
  double &rNormal{xNormal};
  xNormal = 10;
  std::cout << "value of variable we are pointing to is : " << rNormal
            << std::endl;

  // Example 1: A “smart” pointer pointing at a double on the stack.
  double xSmart{5};
  std::unique_ptr<double, void (*)(double *)> pSmart{&xSmart, +[](double *) {}};
  xSmart = 10;
  std::cout
      << "value of variable we are pointing to through a dumb pointer is : "
      << *pSmart << std::endl;

  // Example 2: A smart pointer pointing at a heap-allocated double.
  std::unique_ptr<double> pUselessSmart{std::make_unique<double>(5)};
  double *qUselessSmart{pUselessSmart.get()};
  *qUselessSmart = 10;
  std::cout
      << "value of variable we are pointing to through a smart pointer is : "
      << *pUselessSmart << std::endl;
}

我上面愚蠢的“智能”指针示例的一个关键缺陷是代码可读性差。按照惯例,a 表示内存所有权。它可以将所有权转移到其他实例,可能通过 s 和调用站点,使用 R-value() 引用和相应的复制构造函数并获取引用(与对应的 d)。但是,一个不应该指向它不拥有的东西,即它不能/不应该的东西,例如堆栈内存、另一个人拥有的内存(这与它的名字相悖)等。std::unique_ptrreturn&&operator =()&&const &= deletestd::unique_ptrdeletestd::unique_ptrunique