Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::map::emplace语法有问题_C++_C++11_Std - Fatal编程技术网

C++ std::map::emplace语法有问题

C++ std::map::emplace语法有问题,c++,c++11,std,C++,C++11,Std,我正在尝试将数据放置到std::map中。以下是我尝试过的(从原始来源中删减,但肯定给出了想法): 模板类trie{ 私人: 地图儿童; std::唯一的父项; //后来 公众: trie(常量trie和其他,trie*常量父项): 父{parent} { for(自动const&it:其他子项) 儿童就业(it.first,{*it.second}); } }; 错误如下: trie.h: In instantiation of ‘trie<T>::trie(const trie

我正在尝试将数据放置到
std::map
中。以下是我尝试过的(从原始来源中删减,但肯定给出了想法):

模板类trie{
私人:
地图儿童;
std::唯一的父项;
//后来
公众:
trie(常量trie和其他,trie*常量父项):
父{parent}
{
for(自动const&it:其他子项)
儿童就业(it.first,{*it.second});
}
};
错误如下:

trie.h: In instantiation of ‘trie<T>::trie(const trie<T>&, trie<T>*) [with T = std::basic_string<char>]’:
main.cpp:7:23:   required from here
trie.h:90:3: error: no matching function for call to ‘std::map<char, std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > >, std::less<char>, std::allocator<std::pair<const char, std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > > > > >::emplace(const char&, <brace-enclosed initializer list>)’
   children.emplace(it.first, {*it.second});
   ^
trie.h:90:3: note: candidate is:
In file included from /usr/include/c++/4.8.1/map:61:0,
                 from trie.h:4,
                 from main.cpp:2:
/usr/include/c++/4.8.1/bits/stl_map.h:540:2: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::emplace(_Args&& ...) [with _Args = {}; _Key = char; _Tp = std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > >; _Compare = std::less<char>; _Alloc = std::allocator<std::pair<const char, std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > > > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const char, std::unique_ptr<trie<std::basic_string<char> >, std::default_delete<trie<std::basic_string<char> > > > > >]
  emplace(_Args&&... __args)
  ^
/usr/include/c++/4.8.1/bits/stl_map.h:540:2: note:   candidate expects 0 arguments, 2 provided
trie.h:在“trie::trie(const-trie&,trie*)[with T=std::basic_string]”的实例化中:
main.cpp:7:23:此处需要
trie.h:90:3:错误:调用“std::map::emplace(const char&,)”时没有匹配的函数
儿童就业(it.first,{*it.second});
^
trie.h:90:3:注:候选人为:
在/usr/include/c++/4.8.1/map:61:0中包含的文件中,
从trie.h:4,
来自main.cpp:2:
/usr/include/c++/4.8.1/bits/stl_-map.h:540:2:注:std::pair std::map::emplace(_-Args&&&…[with _-Args={};_-Key=char;_-Tp=std::unique_-ptr;_-Compare=std::less;_-Alloc=std::分配器;typename std:_-Rb_-tree::iterator=std:_-Rb-tree=std:_-Rb-tree迭代器]
安放(_参数&&…_参数)
^
/usr/include/c++/4.8.1/bits/stl_-map.h:540:2:注意:候选者需要0个参数,提供2个
所以我的问题是:

如何正确初始化map元素,目标是深度复制指向的trie,并且没有不必要的复制/移动?


提前谢谢

通过传递
{*it.second}
作为值的初始化器,您实际上是在尝试使用
trie
初始化
std::unique_ptr
。我相信你在寻找这个:

public:
trie(const trie<T>& other, trie<T>* const parent) :
parent{parent}
{
    for(auto const &it : other.children) {
        // Separate creation of unique_ptr for exception safety, thanks to @DanielFrey
        std::unique_ptr<trie<T>> p(new trie<T>(*it.second));
        children.emplace(it.first, std::move(p));
    }
}
公共:
trie(常量trie和其他,trie*常量父项):
父{parent}
{
for(自动const&it:其他子项){
//由于@DanielFrey,为异常安全单独创建了唯一的_ptr
std::unique_ptr p(新trie(*it.second));
儿童就业(it.first,std::move(p));
}
}
请注意,您还必须提供一个复制构造函数,因为默认构造函数已被删除,因为您的类具有不可复制的成员


与问题无关,但您应该重新考虑您的设计:您很可能有一个所有权循环。如果
trie
unique\u ptr
存储到其子级,而这些子级将
unique\u ptr
存储回其父级,则会出现双重删除错误。将其中一个(可能是指向父级的指针)转换为原始指针。原始指针可以在不参与所有权的情况下进行观察。

您需要

for(auto const &it : other.children) {
    std::unique_ptr<trie<T>> element(new trie<T>(*it.second));
    children.emplace(it.first, std::move(element));
}

作为所有智能指针的经验法则,您总是使用
std::make.*
或者必须使用单独的行来创建它们。

不会
*它。第二个
解析为对
trie
的引用?你不能从中初始化一个
唯一的\u指针
。在类声明中删除
trie::
,这是额外的限定。这是你真正的代码吗?@MM。好的,谢谢。这是一个复制/粘贴工件;它们实际上在不同的位置。我认为是你在
emplace
抛出时造成了资源泄漏。看看我的答案,了解真正需要什么。非常好的答案。所有权循环的优点;我没想到。如果我在声明中设置了
parent=nullptr
,该函数是否可以用作复制构造函数?此外,是否有一种方法可以在适当的位置构建
唯一的\u ptr
?我看到了@DanielFrey的解释,但我想也许我可以通过
{}
s传递给构造函数。@thirty340-Re-copy-ctor:can-be,取决于它的预期语义。是否要在复制ctor中复制
other.parent
的值?Re-in-place
unique\u ptr
:恐怕这不太可能,它们都只是函数调用,仍然有可能在构建
unique\u ptr
之前先构建
,然后再构建
unique\u ptr
(但是在调用
emplace
之前必须对
新的
进行评估)对于
make_unique
语法,.+1——如此干净!是否因为编译器将省略返回值而更快?(不幸的是,这一点有点没有意义,因为我不打算使用标准草案。)@Thirty340
make_unique
实际上非常简单,只是一个简单的疏忽,它没有包含在C++11中。事实上,它非常简单,您可以自己编写并将其添加到代码中。你可以找到它。正如您在我的回答中所看到的那样,它并不是真的更有效,而是更安全的异常。@Thirty340只是为了澄清:使用
make_unique
很可能与就地构造一样有效,因为它只是一个指针,我很确定优化器将能够消除所有开销。哦,好的,谢谢链接。我所说的“更快”是指,直接使用
make_unique
会比
std::move
(即使
make_unique
按值返回)更高效吗?@thirty340同样,
unique_ptr
是一个小而简单的对象,很可能没有“更高效”的对象。它在内部只是一个简单的指针,通过复制它并将源代码设置为
0
“移动”它-很容易跟踪并为编译器优化。主要区别在于跟踪指针的生命周期,并确保在所有情况下(包括涉及异常的情况)都调用
delete
for(auto const &it : other.children) {
    std::unique_ptr<trie<T>> element(new trie<T>(*it.second));
    children.emplace(it.first, std::move(element));
}
for(auto const &it : other.children) {
    children.emplace(it.first, std::make_unique<trie<T>>(*it.second));
}