C++x0 unique_ptr GCC 4.4.4

4

我正在尝试使用C++x0中的unique_ptr,方法如下:

#include <memory> 

使用 -std=c++0x 编译时,出现了许多错误,以下是其中的一个例子。

/usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../include/c++/4.4.4/bits/unique_ptr.h:214: error: deleted function ‘std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = Descriptor, _Tp_Deleter = std::default_delete<Descriptor>]’

更新**** 这是我正在尝试的事情,我已经删除了typedefs,以便您可以清晰地看到类型。

static std::unique_ptr<SomeType> GetSomeType()
{
    std::unique_ptr<SomeType> st("Data","Data2",false);

    std::unique_ptr<OtherType> ot("uniportantconstructor data");

    st->Add(ot);

    return st;

}

//Public method of SomeType
  void Add(std::unique_ptr<OtherType> ot)
  {
    //otmap is std::map<std::string,std::unique_ptr<OtherType> >
    //mappair is std::Pair<std::string,std::unique_ptr<OtherType> >
     otMap.Insert(mappair(ot->name(),ot)); 
  }

更新:

如果我的类SomeType有一个方法,它可以返回Map中的元素(使用key),如下所示:

std::unique_ptr<OtherType> get_othertype(std::string name)
{
   return otMap.find(name);
}

那么这将确保调用者收到的是映射中的指针,而不是副本?

我非常确定unique_ptr没有Add方法。你是否意思是通过st->Add方法实现? - fredoverflow
好的,我修复了。抱歉,我是凭记忆打的,没有编译或其他操作。 - Mark
3个回答

4

看起来你正在尝试使用复制构造函数,但它不存在。如果你的调用代码像这样:

T *ptr = /* whatever */;
std::unique_ptr<T> up = ptr;

你需要将第二行更改为以下内容:
std::unique_ptr<T> up (ptr);

原始版本(基本上)将赋值隐式转换为:

std::unique_ptr<T> up (std::unique_ptr<T>(ptr));

复制构造函数已被删除。 "deleted function" 是C++0x的术语,用于显式删除隐式特殊成员函数。在这种情况下,是复制构造函数。

谢谢,这个错误的解释应该会在将来有所帮助。 - Mark
这是否意味着我不能将unique_ptr作为参数传递或从函数中返回它? - Mark
3
我猜测你的代码;是否可以发布一小段代码片段? - Steve M
1
@Mark:它们的意义完全不同。unique_ptr 表示对象不会与其他指针共享。而 auto_ptr 隐含了所有权的转移,你必须在 unique_ptr 中明确表示,除非涉及到右值引用的规则(例如通过值返回本地 unique_ptr)。 - UncleBens
这里的问题不是缺少复制构造函数,而只是接受指针的构造函数被声明为explicitexplicit构造函数在复制初始化语法中基本上会被忽略。请注意,“复制初始化”并不意味着复制,而可能涉及移动构造。如果将接受指针的构造函数改为隐式,则您的第一个和第三个示例将编译通过。 - sellibitze
显示剩余4条评论

4
std::unique_ptr<OtherType> ot("unimportant constructor data");
st->Add(ot);

如果一个函数接收一个 unique_pointer,那么你不能传递一个左值(lvalue),因为 unique_pointer 没有拷贝构造函数。你必须移动这个左值(将其转换为xvalue)或者传递一个纯右值(prvalue):

// pass an xvalue:
std::unique_ptr<OtherType> ot("unimportant constructor data");
st->Add(std::move(ot));
// note: ot is now empty

// pass a prvalue:
st->Add(std::unique_ptr<OtherType>("unimportant constructor data"));

Add 方法内部,事情会变得有点复杂。首先,你需要从 ot 移动,因为形式参数总是 lvalues(因为它们有名称)。其次,你不能从 ot 移动并将 ot->name() 作为参数传递给 mappair 函数,因为 C++ 中参数的求值顺序是未指定的。因此,在从 ot 移动之前,我们必须在单独的语句中获取 ot->name()

void Add(std::unique_ptr<OtherType> ot)
{
    auto name = ot->name();
    otMap.Insert(mappair(name, std::move(ot))); 
}

希望这能有所帮助。请注意,在任何(理智的)情况下,两个unique_ptr对象都不能指向同一个物体。如果您需要该功能,则unique_ptr不是您想要的。


不要忘记包含 <utility> 以获取 std::move - sellibitze

1
正如@Steve所说,您可能正在使用复制构造函数,unique_ptr不支持复制语义,如果您想将值移动到另一个unique_ptr,则必须move它。
 unique_ptr<T> other = std::move(orig); // orig is now null

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接