简体   繁体   English

C ++ unique_ptr和map

[英]C++ unique_ptr and map

I'm trying to use the C++0x unique_ptr class inside a map like so: 我试图使用的C ++ 0x unique_ptr一个内部map ,像这样:

// compile with `g++ main.cpp -std=gnu++0x`

#include <string.h>    
#include <map>
#include <memory>

using namespace std;

struct Foo {
    char *str;    
    Foo(char const *str_): str(strdup(str_)) {}
};

int main(void) {
    typedef std::map<int, unique_ptr<Foo>> Bar;
    Bar bar;
    auto a = bar.insert(Bar::value_type(1, new Foo("one")));
    return 0;
}

However GCC gives me the following error (shortened, I think this is the relevant part, please test on your own C++ compiler): 但是GCC给了我以下错误(缩短了,我认为这是相关部分,请在您自己的C ++编译器上测试):

main.cpp:19:   instantiated from here
/usr/include/c++/4.4/bits/unique_ptr.h:214: error: deleted function ‘std::unique_ptr::unique_ptr(const std::unique_ptr&) [with _Tp = Foo, _Tp_Deleter = std::default_delete]’
/usr/include/c++/4.4/bits/stl_pair.h:68: error: used here

I'm really not sure what I've done wrong, this works on MSVC. 我真的不确定我做错了什么,这适用于MSVC。 I have found very similar questions, that seem alike, however their solutions do not work for me. 我发现了非常相似的问题,看似相似,但是他们的解决方案对我不起作用。

matt@stanley:/media/data/src/c++0x-test$ gcc --version
gcc-4.4.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3

First: Your class Foo is really a very bad approximation of std::string. 第一:你的类Foo实际上是std :: string的非常差的近似值。 I predict lots of memory leaks. 我预测会有很多内存泄漏。 (Search for "rule of three".) (搜索“三规则”。)

Second: A pointer is not implicitly convertible to a unique_ptr object (for safety reasons). 第二:指针不能隐式转换为unique_ptr对象(出于安全原因)。 But the templated pair constructor requires the arguments to be implicitly convertible to the respective value types. 但是模板化对构造函数要求参数可以隐式转换为相应的值类型。 GCC seems to allow this but it is a bug. 海湾合作委员会似乎允许这样,但这是一个错误。 You have to create the unique_ptr object manually. 您必须手动创建unique_ptr对象。 Unfortunately the C++0x draft lacks the following, very useful function template that eases the creation of temporary unique_ptr objects. 不幸的是,C ++ 0x草案缺少以下非常有用的函数模板,可以简化临时unique_ptr对象的创建。 It's also exception-safe: 它也是异常安全的:

template<class T, class...Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
    std::unique_ptr<T> ret (new T(std::forward<Args>(args)...));
    return ret;
}

In addition, let's use the new emplace function instead of insert : 另外,让我们使用新的emplace函数而不是insert

auto a = bar.emplace(1,make_unique<Foo>("one"));

emplace forwards both arguments to the corresponding pair constructor. emplace将两个参数转发给相应的对构造函数。

The actual problem you witnessed is that the pair constructor tried to copy a unique_ptr even though such an object is only "movable". 您目击的实际问题是,对构造函数尝试复制unique_ptr,即使这样的对象只是“可移动”。 It seems that GCC's C++0x support is not yet good enough to handle this situation correctly. 似乎GCC的C ++ 0x支持还不足以正确处理这种情况。 From what I can tell, my line from above should work according to the current standard draft (N3126). 据我所知,我上面的线应该按照现行标准草案(N3126)运作。

Edit: I just tried the following as a workaround using GCC 4.5.1 in experimental C++0x mode: 编辑:我刚尝试以下作为在实验C ++ 0x模式下使用GCC 4.5.1的变通方法:

map<int,unique_ptr<int> > themap;
themap[42].reset(new int(1729));

This is also supposed to work in the upcoming standard but GCC rejects it as well. 这也应该适用于即将推出的标准,但GCC也拒绝它。 Looks like you have to wait for GCC to support unique_ptr in maps and multimaps. 看起来你必须等待GCC在地图和多地图中支持unique_ptr。

I don't believe it's possible to correctly use unique_ptr in a map::insert yet. 我不相信可以在map::insert正确使用unique_ptr Here's the GCC bug for it: 这是GCC的错误:

Bug 44436 - [C++0x] Implement insert(&&) and emplace* in associative and unordered containers 错误44436 - [C ++ 0x]在关联和无序容器中实现insert(&&)emplace*

It looks like it may be fixed for GCC 4.6 , but it won't build from SVN on vanilla Ubuntu 10.04.1 to confirm. 对于GCC 4.6来说 ,它看起来可能是固定的 ,但它不会在SVU上为vanilla Ubuntu 10.04.1构建来确认。

Update0 Update0

This is not working as of GCC svn r165422 (4.6.0). 这不适用于GCC svn r165422(4.6.0)。

I've just been tinkering with unique_ptr in gcc 4.6.0. 我刚刚在gcc 4.6.0中修改了unique_ptr。 Here's some (very ugly) code which works correctly: 这里有一些(非常难看的)代码可以正常工作:

std::map<int, std::unique_ptr<int> > table;
table.insert(std::pair<int, std::unique_ptr<int>>(15, std::unique_ptr<int>(new int(42))));
table[2] = std::move(table[15]);
for (auto& i : table)
{
    if (i.second.get())
        printf("%d\n", *i.second);
    else
    {
        printf("empty\n");
        i.second.reset(new int(12));
    }
}
printf("%d\n", *table[15]);

The output is 42, empty, 12 - so apparently it works. 输出是42,空,12 - 所以显然它的工作原理。 As far as I can tell, the only 'problem' is that awful looking insert command. 据我所知,唯一的“问题”是看起来很糟糕的插入命令。 'emplace' isn't implemented in gcc 4.6.0 'emplace'未在gcc 4.6.0中实现

尝试使用地图的emplace方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM