标签: unique-ptr

对于像所有权语义这样的原始指针返回unique_ptr的不良做法?

我编写了一个静态工厂方法,它返回从另一个数据对象填充的新Foobar对象.我最近一直沉迷于所有权语义,我想知道我是否通过这种工厂方法返回一个正确的信息unique_ptr.

class Foobar {
public:
    static unique_ptr<Foobar> factory(DataObject data);
}
Run Code Online (Sandbox Code Playgroud)

我的目的是告诉客户端代码他们拥有指针.没有智能指针,我只会回来Foobar*.但是,我想强制删除这个内存以避免潜在的错误,所以这unique_ptr似乎是一个合适的解决方案.如果客户端想要延长指针的生命周期,他们只需在调用.release()后调用unique_ptr.

Foobar* myFoo = Foobar::factory(data).release();
Run Code Online (Sandbox Code Playgroud)

我的问题分为两部分:

  1. 这种方法是否传达了正确的所有权语义?
  2. 返回unique_ptr而不是原始指针这是一个"坏习惯" 吗?

c++ smart-pointers ownership-semantics unique-ptr

49
推荐指数
3
解决办法
2万
查看次数

unique_ptr的动态转换

正如Boost中的情况一样,C++ 11提供了一些用于转换的函数shared_ptr:

std::static_pointer_cast
std::dynamic_pointer_cast
std::const_pointer_cast
Run Code Online (Sandbox Code Playgroud)

但是,我想知道为什么没有等效功能unique_ptr.

考虑以下简单示例:

class A { virtual ~A(); ... }
class B : public A { ... }

unique_ptr<A> pA(new B(...));

unique_ptr<A> qA = std::move(pA); // This is legal since there is no casting
unique_ptr<B> pB = std::move(pA); // This is not legal

// I would like to do something like:
// (Of course, it is not valid, but that would be the idea)
unique_ptr<B> pB = std::move(std::dynamic_pointer_cast<B>(pA));
Run Code Online (Sandbox Code Playgroud)

是否有任何理由不鼓励这种使用模式,因此,shared_ptr没有提供与现有模式相同的功能unique_ptr …

c++ casting smart-pointers unique-ptr c++11

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

错误:'unique_ptr'不是'std'的成员

我想它是非常自我解释的 - 我似乎无法使用C++ 11的功能,即使我认为我已经正确设置了所有东西 - 这可能意味着我没有.

这是我的代码:

#include <cstdlib>
#include <iostream>

class Object {
    private:
        int value;

    public:
        Object(int val) {
            value = val;
        }

        int get_val() {
            return value;
        }

        void set_val(int val) {
            value = val;
        }
};

int main() {

    Object *obj = new Object(3);
    std::unique_ptr<Object> smart_obj(new Object(5));
    std::cout << obj->get_val() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是我的g ++版本:

ubuntu@ubuntu:~/Desktop$ g++ --version
g++ (Ubuntu/Linaro 4.7.3-2ubuntu1~12.04) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see …
Run Code Online (Sandbox Code Playgroud)

c++ g++ unique-ptr c++11

49
推荐指数
1
解决办法
5万
查看次数

将unique_ptr传递给函数

我正试图"现代化"一些现有的代码.

  • 我有一个类,当前有一个成员变量"Device*device_".
  • 它使用new在一些初始化代码中创建一个实例,并在destructory中有一个"delete device_".
  • 此类的成员函数调用许多其他函数,这些函数将Device*作为参数.

这很好用,但为了"现代化"我的代码,我认为我应该更改要定义的变量,"std::unique_ptr<Device> device_"并删除显式调用delete,这使得代码更安全,通常更好.

我的问题是这个 -

  • 那么我应该如何将device _变量传递给需要它作为参数的所有函数?

我可以调用.get来获取每个函数调用中的原始指针.但这看起来很丑陋,浪费了一些首先使用unique_ptr的原因.

或者我可以更改每个函数,以便不使用"Device*"类型的参数,而是使用"std :: unique_ptr&"类型的参数.哪个(对我来说)有点模糊了函数原型,并使它们难以阅读.

这是什么最佳做法?我错过了其他选择吗?

c++ smart-pointers unique-ptr

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

使用C++ 11 for()循环遍历vector <unique_ptr <mytype >>

我有以下一批代码:

std::vector<std::unique_ptr<AVLTree_GeeksforGeeks>> AVLArray(100000);

/* Let's add some objects in the vector */
AVLTree_GeeksforGeeks *avl = new AVLTree_GeeksforGeeks();
avl->Insert[2]; avl->Insert[5]; AVL->Insert[0];
unique_ptr<AVLTree_GeeksforGeeks> unique_p(avl);
AVLArray[0] = move(unique_p);
/* we do this for a number of other trees, let's say another 9...
...
...
Now the vector has objects up until AVLTree[9] */

/* Let's try iterating through its valid, filled positions */
for(auto i : AVLTree )
{
   cout << "Hey there!\n";    //This loop should print 10 "Hey there"s.
}
Run Code Online (Sandbox Code Playgroud)

茹罗.最后一部分,for()循环中的编译错误. …

c++ vector unique-ptr c++11

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

那么unique_ptr可以在stl集合中安全使用吗?

我对unique_ptr和rvalue move哲学很困惑.

假设我们有两个集合:

std::vector<std::auto_ptr<int>> autoCollection;
std::vector<std::unique_ptr<int>> uniqueCollection;
Run Code Online (Sandbox Code Playgroud)

现在我希望以下内容失败,因为没有人知道算法在内部做了什么,也许还在制作内部数据透视副本等,从而剥夺了auto_ptr的所有权:

std::sort(autoCollection.begin(), autoCollection.end());
Run Code Online (Sandbox Code Playgroud)

我明白了 并且编译器正确地不允许这种情况发生.

但后来我这样做:

std::sort(uniqueCollection.begin(), uniqueCollection.end());
Run Code Online (Sandbox Code Playgroud)

这编译.我不明白为什么.我不认为unique_ptrs可以复制.这是否意味着不能采用枢轴值,因此排序效率较低?或者这个转轴实际上是一个移动,实际上和auto_ptrs的集合一样危险,编译器应该不允许这样做?

我想我错过了一些重要的信息,所以我急切等待有人给我提供啊哈!时刻.

c++ auto-ptr unique-ptr c++11

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

std :: unique_ptr用法

std::unique_ptr<int> p1(new int);
std::unique_ptr<int> p2(new int);
p2=p1;
Run Code Online (Sandbox Code Playgroud)

在这里似乎p1不再是"唯一的",因为p2也指它

这是合法的c ++?unique_ptr有copy_semantics吗?如果不是,并且它只有移动语义,那么在将p1分配给p2后p1是否设置为NULL?

编辑:

好的,所以正确的版本是

 p2=std::move(p1)
Run Code Online (Sandbox Code Playgroud)

据此,在此分配后,p1无效?与auto_ptr的区别在哪里?所有权明确规定所有权转让比隐式更安全,因为我认为auto_ptr是这种情况

c++ unique-ptr c++11

41
推荐指数
2
解决办法
5万
查看次数

将std :: unique_ptr <Derived>转换为std :: unique_ptr <Base>

假设我有处理基类和派生类的工厂函数:

#include <memory>

using namespace std;

struct B { virtual ~B() {} };
struct D : B {};

unique_ptr<B> MakeB()
{
    auto b = unique_ptr<B>( new B() );
    return b; // Ok!
}

unique_ptr<B> MakeD()
{
    auto d = unique_ptr<D>( new D() );
    return d; // Doh!
}
Run Code Online (Sandbox Code Playgroud)

在上面的最后一行,我需要move(d)为了使它工作,否则我得到"错误:无效转换std::unique_ptr<D>std::unique_ptr<D>&&." 我的直觉说,在这种情况下,编译器应该知道它可以隐式地创建d一个rvalue并将其移动到基指针中,但事实并非如此.

这在我的编译器(gcc 4.8.1和VS2012)中是不可靠的吗?预期的设计unique_ptr?标准有缺陷吗?

c++ unique-ptr c++11 c++14

41
推荐指数
1
解决办法
9057
查看次数

C++ std :: unique_ptr:为什么lambdas没有任何大小的费用?

我正在阅读"Effective Modern C++".在与std::unique_ptr它相关的项目中声明如果自定义删除器是无状态对象,则不会出现大小费用,但如果它是函数指针或std::function大小费用发生.你能解释一下原因吗?

假设我们有以下代码:

auto deleter_ = [](int *p) { doSth(p); delete p; };
std::unique_ptr<int, decltype(deleter_)> up(new int, deleter_);
Run Code Online (Sandbox Code Playgroud)

根据我的理解,unique_ptr应该有一个类型的对象decltype(deleter_)并分配deleter_给该内部对象.但显然这不是正在发生的事情.你能用最小的代码示例来解释这背后的机制吗?

c++ unique-ptr c++11 c++14

41
推荐指数
4
解决办法
3235
查看次数

对unique_ptrs集的原始指针查找

我经常发现自己想写这样的代码:

class MyClass
{
public:
  void addObject(std::unique_ptr<Object>&& newObject);

  void removeObject(const Object* target);

private:
  std::set<std::unique_ptr<Object>> objects;
};
Run Code Online (Sandbox Code Playgroud)

但是,很多std :: set接口对std :: unique_ptrs都没用,因为查找函数需要std :: unique_ptr参数(我显然没有这些参数,因为它们由集合本身拥有).

我可以想到两个主要的解决方案.

  1. 创建临时unique_ptr以进行查找.例如,上面的removeObject()可以实现如下:

    void MyClass::removeObject(const Object* target)
    {
      std::unique_ptr<Object> targetSmartPtr(target);
      objects.erase(targetSmartPtr);
      targetSmartPtr.release();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将原始指针映射替换为unique_ptrs.

      // ...
      std::map<const Object*, std::unique_ptr<Object>> objects;
    };
    
    Run Code Online (Sandbox Code Playgroud)

然而,对我来说,两者似乎都有点愚蠢.在解决方案1中,erase()不是noexcept,因此临时unique_ptr可能会删除它实际上不拥有的对象,而2需要不必要地为容器存储两倍.

我知道Boost的指针容器,但与现代C++ 11标准库容器相比,它们目前的功能有限.

我最近在阅读有关C++ 14的内容,并且遇到了"将异构比较查找添加到关联容器".但是形成我对它的理解,查找类型必须与键类型相当,但原始指针不能与unique_ptrs相比.

任何人都知道更优雅的解决方案或即将添加的C++解决了这个问题?

c++ unique-ptr c++11 c++14

40
推荐指数
1
解决办法
3996
查看次数