标签: smart-pointers

C的智能指针/安全内存管理?

我和其他许多人一样,使用智能指针在C++中包含不安全的内存操作,使用RAII等等,已经取得了巨大的成功.但是,当您具有析构函数,类,运算符重载等时,包装内存管理更容易实现.

对于使用原始C99编写的人,您可以在哪里指出(没有双关语)来帮助安全内存管理?

谢谢.

c memory pointers smart-pointers c99

43
推荐指数
4
解决办法
2万
查看次数

std :: shared_ptr初始化:make_shared <Foo>()vs shared_ptr <T>(new Foo)

有什么区别:

std::shared_ptr<int> p = std::shared_ptr<int>( new int );
Run Code Online (Sandbox Code Playgroud)

std::shared_ptr<int> p = std::make_shared< int >();
Run Code Online (Sandbox Code Playgroud)

我应该选择哪一个?为什么?

PS相当肯定这已经得到了答案,但我找不到类似的问题.

c++ smart-pointers shared-ptr c++11

43
推荐指数
3
解决办法
6万
查看次数

使用observer_ptr

std::observer_ptr库基础技术规范V2 中的构造究竟有什么意义?

在我看来,它所做的一切都是裸露的T*,如果不增加动态内存安全性,这似乎是一个多余的步骤.

在我的所有代码中,我使用std::unique_ptr了我需要明确拥有对象的位置以及std::shared_ptr可以共享对象所有权的位置.

这非常有效并且可以防止意外解除引用已经被破坏的对象.

std::observer_ptr 当然,不保证观察到的物体的寿命.

如果它是从a构造的,std::unique_ptr或者std::shared_ptr我会看到在这样的结构中使用,但任何简单使用的代码T*可能只是继续这样做,如果他们计划移动到任何它将是std::shared_ptr和/或std::unique_ptr(取决于在使用上).


给出一个简单的示例函数:

template<typename T>
auto func(std::observer_ptr<T> ptr){}
Run Code Online (Sandbox Code Playgroud)

如果停止智能指针在观察它们时销毁它们存储的对象将会有用.

但如果我想观察std::shared_ptrstd::unique_ptr我必须写:

auto main() -> int{
    auto uptr = std::make_unique<int>(5);
    auto sptr = std::make_shared<int>(6);
    func(uptr.get());
    func(sptr.get());
}
Run Code Online (Sandbox Code Playgroud)

这使得它不比以下更安全:

template<typename T>
auto func(T *ptr){}
Run Code Online (Sandbox Code Playgroud)

那么,这个新结构的用途是什么?

它只是用于自我记录的来源吗?

c++ smart-pointers c++17

42
推荐指数
5
解决办法
6748
查看次数

5 法则(对于构造函数和析构函数)是否过时了?

5 规则指出,如果一个类有一个用户声明的析构函数、复制构造函数、复制赋值构造函数、移动构造函数或移动赋值构造函数,那么它必须有其他 4 个。

但今天我突然明白了:你什么时候需要用户定义的析构函数、复制构造函数、复制赋值构造函数、移动构造函数或移动赋值构造函数?

在我的理解中,隐式构造函数/析构函数适用于聚合数据结构。但是,管理资源的类需要用户定义的构造函数/析构函数。

但是,不能将所有资源管理类都使用智能指针转换为聚合数据结构吗?

例子:

// RAII Class which allocates memory on the heap.
class ResourceManager {
    Resource* resource;
    ResourceManager() {resource = new Resource;}
    // In this class you need all the destructors/ copy ctor/ move ctor etc...
    // I haven't written them as they are trivial to implement
};
Run Code Online (Sandbox Code Playgroud)

对比

class ResourceManager {
    std::unique_ptr<Resource> resource;
};
Run Code Online (Sandbox Code Playgroud)

现在示例 2 的行为与示例 1 完全相同,但所有隐式构造函数都可以工作。

当然,你不能 copy ResourceManager,但如果你想要不同的行为,你可以使用不同的智能指针。

关键是当智能指针已经有那些隐式构造函数可以工作时,你不需要用户定义的构造函数。

我认为拥有用户定义的构造函数的唯一原因是:

  1. 你不能在一些低级代码中使用智能指针(我非常怀疑这种情况)。

  2. 您正在自己实现智能指针。

但是,在普通代码中,我看不出有任何理由使用用户定义的构造函数。

我在这里错过了什么吗?

c++ smart-pointers raii resource-management

40
推荐指数
5
解决办法
4031
查看次数

如何将删除函数传递给make_shared?

从C++ 11开始,由于几个原因,开发人员倾向于将智能指针类用于动态生命周期对象.而对于那些新的智能指针类,标准,甚至建议不使用运营商,new而是建议使用make_sharedmake_unique避免一些容易出错.

如果我们喜欢使用智能指针类shared_ptr,我们可以构建一个类似的,

shared_ptr<int> p(new int(12));
Run Code Online (Sandbox Code Playgroud)

我们还希望将自定义删除器传递给智能指针类,

shared_ptr<int> p(new int(12), deleter);
Run Code Online (Sandbox Code Playgroud)

另一方面,如果我们喜欢使用make_shared分配,例如.int,而不是使用newshared_ptr构造函数,就像上面的第一个表达式,我们可以使用

auto ip = make_shared<int>(12);
Run Code Online (Sandbox Code Playgroud)

但是,如果我们也希望将自定义删除器传递给make_shared,那么有没有正确的方法呢?好像编译器,至少gcc,给出错误,

auto ip = make_shared<int>(12, deleter);
Run Code Online (Sandbox Code Playgroud)

c++ smart-pointers shared-ptr make-shared c++11

39
推荐指数
3
解决办法
1万
查看次数

为什么unique_ptr实例化编译为比原始指针更大的二进制?

我总是认为std::unique_ptr与使用原始指针相比没有任何开销.但是,编译以下代码

#include <memory>

void raw_pointer() {
  int* p = new int[100];
  delete[] p;
}

void smart_pointer() {
  auto p = std::make_unique<int[]>(100);
}
Run Code Online (Sandbox Code Playgroud)

with g++ -std=c++14 -O3生成以下程序集:

raw_pointer():
        sub     rsp, 8
        mov     edi, 400
        call    operator new[](unsigned long)
        add     rsp, 8
        mov     rdi, rax
        jmp     operator delete[](void*)
smart_pointer():
        sub     rsp, 8
        mov     edi, 400
        call    operator new[](unsigned long)
        lea     rdi, [rax+8]
        mov     rcx, rax
        mov     QWORD PTR [rax], 0
        mov     QWORD PTR [rax+392], 0
        mov     rdx, rax
        xor …
Run Code Online (Sandbox Code Playgroud)

c++ assembly smart-pointers

39
推荐指数
1
解决办法
1300
查看次数

工厂功能的最佳智能指针返回类型是什么?

关于智能指针和新的C++ 11/14功能,我想知道具有这些功能的类的最佳实践返回值和函数参数类型是什么:

  1. 一个工厂函数(在类之外),它创建对象并将它们返回给类的用户.(例如,打开文档并返回可用于访问内容的对象.)

  2. 实用程序函数接受来自工厂函数的对象,使用它们,但不取得所有权.(例如,计算文档中单词数量的函数.)

  3. 在返回对象后保持对对象引用的函数(如获取对象副本的UI组件,以便它可以根据需要在屏幕上绘制内容.)

工厂功能的最佳返回类型是什么?

  • 如果它是一个原始指针,用户将delete正确地使用它,这是有问题的.
  • 如果它返回a,unique_ptr<>则用户无法共享它.
  • 如果它是一个shared_ptr<>那么我将不得不传遍各地的shared_ptr<>类型?这就是我现在正在做的事情,它导致了问题,因为我正在获取循环引用,防止对象被自动销毁.

效用函数的最佳参数类型是什么?

  • 我想通过引用传递将避免不必要地增加智能指针引用计数,但这有什么缺点吗?想到的主要原因是它阻止我将派生类传递给带有基类类型参数的函数.
  • 有没有什么方法可以让调用者明白它不会复制对象?(理想情况下,如果函数体尝试复制对象,代码将无法编译.)
  • 有没有办法使它独立于使用的智能指针类型?(也许拿一个原始指针?)
  • 是否有可能有一个const参数来说明该函数不会修改对象,而不会破坏智能指针的兼容性?

保持对象引用的函数的最佳参数类型是什么?

  • 我猜shared_ptr<>是这里唯一的选择,这可能意味着工厂类必须返回一个shared_ptr<>,对吗?

这里有一些代码可以编译并希望说明要点.

#include <iostream>
#include <memory>

struct Document {
    std::string content;
};

struct UI {
    std::shared_ptr<Document> doc;

    // This function is not copying the object, but holding a
    // reference to it to make sure it doesn't get destroyed.
    void setDocument(std::shared_ptr<Document> newDoc) {
        this->doc = newDoc;
    }
    void redraw() {
        // …
Run Code Online (Sandbox Code Playgroud)

c++ smart-pointers const-correctness c++11

38
推荐指数
3
解决办法
1万
查看次数

C++ 11智能指针语义

我已经使用了几年的指针,但我最近才决定转换到C++ 11的智能指针(即唯一,共享和弱).我对它们做了很多研究,这些是我得出的结论:

  1. 独特的指针很棒.他们管理自己的内存,并且像原始指针一样轻量级.首选尽可能多地使用unique_ptr而不是原始指针.
  2. 共享指针很复杂.由于引用计数,它们具有显着的开销.通过const引用传递它们或后悔你的方式的错误.它们不是邪恶的,但应该谨慎使用.
  3. 共享指针应该拥有对象; 在不需要所有权时使用弱指针.锁定weak_ptr具有与shared_ptr复制构造函数相同的开销.
  4. 继续忽略auto_ptr的存在,现在无论如何都不推荐使用它.

因此,考虑到这些原则,我开始修改我的代码库以利用我们新的闪亮智能指针,完全打算清除尽可能多的原始指针.然而,我对如何最好地利用C++ 11智能指针感到困惑.

例如,让我们假设我们正在设计一个简单的游戏.我们认为将虚构的Texture数据类型加载到TextureManager类中是最佳的.这些纹理很复杂,因此按值传递它们是不可行的.此外,让我们假设游戏对象需要特定的纹理,具体取决于它们的对象类型(即汽车,船等).

之前,我会将纹理加载到矢量(或其他容器,如unordered_map)中,并在每个相应的游戏对象中存储指向这些纹理的指针,以便在需要渲染时可以引用它们.让我们假设纹理保证比指针寿命更长.

那么,我的问题是如何在这种情况下最好地利用智能指针.我看到几个选项:

  1. 将纹理直接存储在容器中,然后在每个游戏对象中构造unique_ptr.

    class TextureManager {
      public:
        const Texture& texture(const std::string& key) const
            { return textures_.at(key); }
      private:
        std::unordered_map<std::string, Texture> textures_;
    };
    class GameObject {
      public:
        void set_texture(const Texture& texture)
            { texture_ = std::unique_ptr<Texture>(new Texture(texture)); }
      private:
        std::unique_ptr<Texture> texture_;
    };
    
    Run Code Online (Sandbox Code Playgroud)

    然而,我对此的理解是,新的纹理将从传递的引用中复制构造,然后由unique_ptr拥有.这让我觉得非常不受欢迎,因为我会使用与使用它的游戏对象一样多的纹理副本 - 击败指针点(没有双关语意).

  2. 不直接存储纹理,而是存储容器中的共享指针.使用make_shared初始化共享指针.构造游戏对象中的弱指针.

    class TextureManager {
      public:
        const std::shared_ptr<Texture>& texture(const std::string& key) const
            { return textures_.at(key); }
      private:
        std::unordered_map<std::string, std::shared_ptr<Texture>> textures_;
    };
    class GameObject {
      public:
        void set_texture(const std::shared_ptr<Texture>& …
    Run Code Online (Sandbox Code Playgroud)

c++ pointers smart-pointers c++11

37
推荐指数
2
解决办法
7660
查看次数

shared_ptr vs scoped_ptr

scoped_ptr不能复制,并且正在删除范围之外.所以它有点受限制shared_ptr.因此,除了您真正需要限制复制操作的情况之外,shared_ptr最好使用.因为有时您不知道需要创建对象的副本或不需要.所以问题是:除了上面提到的情况之外,我们shared_ptr是否可以考虑使用更好(或推荐)代替scoped_ptr.是否scoped_ptr更快地工作shared_ptr,或者它有什么优势?

谢谢!

c++ boost smart-pointers shared-ptr scoped-ptr

36
推荐指数
3
解决办法
4万
查看次数

c ++ 11中的intrusive_ptr

C++ 11有相同的东西boost::intrusive_ptr吗?

我的问题是我的C++代码有一个C风格的界面.接口的两端都可以使用C++,但出于兼容性原因需要公开C接口.我无法使用,std::shared_ptr因为我必须通过两个(或更多)智能指针来管理对象.我无法找到类似的解决方案boost::intrusive_ptr.

c++ boost smart-pointers shared-ptr c++11

33
推荐指数
1
解决办法
2万
查看次数