C ++ unique_ptr和map
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C ++ unique_ptr和map相关的知识,希望对你有一定的参考价值。
我试图在C++0x中使用unique_ptr
class 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;
}
但是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
我真的不确定我做错了什么,这适用于MSVC。我发现了非常similar问题,看似相似,但他们的解决方案对我不起作用。
matt@stanley:/media/data/src/c++0x-test$ gcc --version gcc-4.4.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3
第一:你的类Foo实际上是std :: string的非常差的近似值。我预测会有很多内存泄漏。 (搜索“三规则”。)
第二:指针不能隐式转换为unique_ptr对象(出于安全原因)。但是模板化对构造函数要求参数可以隐式转换为相应的值类型。海湾合作委员会似乎允许这样,但这是一个错误。您必须手动创建unique_ptr对象。不幸的是,C ++ 0x草案缺少以下非常有用的函数模板,可以简化临时unique_ptr对象的创建。它也是异常安全的:
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;
}
另外,让我们使用新的emplace函数而不是insert:
auto a = bar.emplace(1,make_unique<Foo>("one"));
emplace将两个参数转发给相应的对构造函数。
您目击的实际问题是,对构造函数尝试复制unique_ptr,即使这样的对象只是“可移动”。似乎GCC的C ++ 0x支持还不足以正确处理这种情况。据我所知,我上面的线应该按照现行标准草案(N3126)运作。
编辑:我刚尝试以下作为在实验C ++ 0x模式下使用GCC 4.5.1的变通方法:
map<int,unique_ptr<int> > themap;
themap[42].reset(new int(1729));
这也应该适用于即将推出的标准,但GCC也拒绝它。看起来你必须等待GCC在地图和多地图中支持unique_ptr。
我不相信在unique_ptr
中正确使用map::insert
是可能的。这是GCC的错误:
Bug 44436 - [C++0x] Implement insert(&&)
and emplace*
in associative and unordered containers
看起来它可能是fixed for GCC 4.6,但它不会从SVN在香草Ubuntu 10.04.1上构建来确认。
Update0
这不适用于GCC svn r165422(4.6.0)。
我刚刚在gcc 4.6.0中修改了unique_ptr。这里有一些(非常难看的)代码可以正常工作:
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
", *i.second);
else
{
printf("empty
");
i.second.reset(new int(12));
}
}
printf("%d
", *table[15]);
输出是42,空,12 - 所以显然它的工作原理。据我所知,唯一的“问题”是看起来很糟糕的插入命令。 'emplace'未在gcc 4.6.0中实现
尝试使用emplace
方法的地图。
以上是关于C ++ unique_ptr和map的主要内容,如果未能解决你的问题,请参考以下文章
带有 C++11+ unique_ptr 的 Libevent
[C++11]独占的智能指针unique_ptr的初始化和使用