【问题标题】:Smart Pointers(shared_ptr)智能指针(shared_ptr)
【发布时间】:2020-07-10 18:50:20
【问题描述】:

我尝试学习如何使用智能指针。我使用了很长一段时间的普通指针,我认为我需要提升我的技能。

我做了一些研究,我了解智能指针的某些方面,但我尝试在一个清晰的项目中实现以了解智能指针是如何工作的。我试试:

#include <iostream>
#include <array>
#include <memory>

class Entity
{
public:
    Entity()
    {
        std::cout << "Entity called!" << std::endl;
    }
    ~Entity()
    {
        std::cout << "Entity destroyed!" << std::endl;
    }
    void print() { std::cout << "Message!"; }
};

int main()
{
    std::shared_ptr<int>f1(new int[100]);

    f1.get()[1] = 1;
    std::cout << f1.get()[1];
}

一切都好,消息已打印。但是当我尝试时:

#include <iostream>
#include <array>
#include <memory>

class Entity
{
public:
    Entity()
    {
        std::cout << "Entity called!" << std::endl;
    }
    ~Entity()
    {
        std::cout << "Entity destroyed!" << std::endl;
    }
    void print() { std::cout << "Message!"; };
};

int main()
{
    std::shared_ptr<Entity>f1(new Entity[100]);

    f1.get()[1].print();
}

我收到此错误: [img]https://i.imgur.com/U30gTgC.png[/img]

下一个:

int main()
{
    std::shared_ptr<Entity>f1(new Entity[100]);

    (f1.get() + 1)->print();
}

同样的错误。

我尝试使用 std::make_shared:

#include <iostream>
#include <array>
#include <memory>

class Entity
{
public:
    Entity()
    {
        std::cout << "Entity called!" << std::endl;
    }
    ~Entity()
    {
        std::cout << "Entity destroyed!" << std::endl;
    }
    void print() { std::cout << "Message!"; };
};

int main()
{
    std::shared_ptr<Entity>f1 = std::make_shared<Entity>();

    f1->print();
}

一切正常。

我尝试用 int 分配 continue 内存:

#include <iostream>
#include <array>
#include <memory>

class Entity
{
public:
    Entity()
    {
        std::cout << "Entity called!" << std::endl;
    }
    ~Entity()
    {
        std::cout << "Entity destroyed!" << std::endl;
    }
    void print() { std::cout << "Message!"; };
};

int main()
{
    std::shared_ptr<int>f1 = std::make_shared<int>(100);

    f1.get()[1] = 10;
    std::cout << f1.get()[1];
}

消息已打印,输出:10 但错误: https://i.imgur.com/UPu7VZo.png

我尝试了另一种方式:

int main()
{
    std::shared_ptr<int>f1 = std::make_shared<int>(100);

    *(f1.get() +1) = 10;
    std::cout << *(f1.get() + 1);
}

同样的错误。

std::shared_ptr<Entity[]>f1 = std::make_shared<Entity[]>(new Entity[100]);

我有错误...

我尝试做这样的事情:

int main()
{
    Entity* f1 = new Entity[100];

    f1[0].print();
    f1[1].print();
    f1[2].print();

}

但我想使用智能指针。

对于 int,我想像这样分配一些值:

int main()
{
    int* f1 = new int[100];

    f1[0] = 14;
    f1[1] = 20;
    f1[2] = 5;
}

我怎样才能用智能指针做这样的事情。我想使用:std::make_shared(new Entity[100]) 或类似的东西。

我可以尝试使用向量或数组之类的库,但我暂时不想使用这个库。我想暂时保持我的代码清晰。在我理解 100% 智能指针后,我将使用数组和向量库

【问题讨论】:

  • 错误消息是文本。在此处粘贴文本;不要链接到文本图像。
  • 你应该使用std::shared_ptr&lt;Entity[]&gt; 否则容器会尝试调用delete 而不是delete[] 这是错误的stackoverflow.com/questions/1553382/is-delete-equal-to-delete
  • 这能回答你的问题吗? shared_ptr to an array : should it be used?
  • make_shared 创建(“制作”)一个共享对象。它不需要指向对象的指针并“使其共享”。
  • 虽然std::shared_ptr&lt;Entity[]&gt; 是可能的,但std::vector&lt;Entity&gt;std::array&lt;Entity, 100&gt; 更常见。智能指针只是哑指针的替代品之一。标准容器是另一种替代品。

标签: c++ smart-pointers


【解决方案1】:

没有

std::shared_ptr<Entity[]> f1 = std::make_shared<Entity[]>(new Entity[100]);

但是

std::shared_ptr<Entity[]> f1 = std::make_shared<Entity[]>(100);

甚至更简单

auto f1 = std::make_shared<Entity[]>(100);

当您使用make_shared 时,您不应使用newmake_shared 的要点之一是比使​​用 new 时更有效地分配内存。

注意:make_shared的数组形式需要C++20。

【讨论】:

  • 我有错误 :warning C4200: nonstandard extension used: zero-sized array in struct/union
  • 该错误指的是哪一行代码?您要编译到哪个版本的 C++?
  • @ClaudiuAndries 你用的是什么编译器?
  • IDE 它是 Visual Studio 社区,但我认为它是 C++2017/2020
  • 我编译:int main() { std::shared_ptrf1 = std::make_shared(100); } 及之后:pastebin.com/3mEjjb8W
【解决方案2】:

应该为您工作的代码示例是:

int main() {
    std::shared_ptr<Entity[]>f1(new Entity[100]);

    f1.get()[1].print();
}

至于make_shared,你倒霉了——当前的 CPP 标准 17 似乎不支持它(见https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared) 但是,make_shared 仅用于消除分配中的竞争条件,可以手动实现,也可以省略。我鼓励阅读更多相关信息。

【讨论】:

  • 你的代码工作..但我不明白:auto sp = std::make_shared(12); static_assert(std::is_same_v>); std::cout i (100); //编译没有错误我怎样才能访问 f2.get()[1].printf()?我需要制作 static_assert 吗?
  • 和问题2:如何在分配中注意竞争条件,如何手动实现?
  • 第1题没看懂
  • 在问题 2 中,问题是如果 shared_ptr 的构造函数失败,您会泄漏您的分配。 AFAIK,解决它的代码是:
  • shared_ptr p; T* temp_ptr = 新 T();尝试 { p = temp_ptr; } catch(...) { 删除 temp_ptr;扔; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
  • 2017-04-29
  • 1970-01-01
  • 2016-10-09
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
相关资源
最近更新 更多