C++使用删除函数报错
C++ Use of deleted function error
我遇到了很多使用已删除函数的错误。我只是将 weighted_pointer
的指针更改为 unique_ptr
。但是我不明白为什么会出现错误,有什么提示吗?
likeatree
是一个DAG结构,可以根据掩码值指向另一个结构或stdDeque
的元素。
weighted_pointer
的 weight
有 mutable
关键字,因为不会改变集合中的位置。
#include <deque>
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>
#include <memory>
#include <chrono>
using namespace std;
struct likeatree{
unsigned int mask : 3;
void * a;
void * b;
};
struct weighted_pointer{
mutable int weight;
unique_ptr<likeatree> ptr;
};
struct ptrcomp{
bool operator()(const weighted_pointer & lhs, const weighted_pointer & rhs) {
if(lhs.ptr->mask < rhs.ptr->mask)
return true;
if(lhs.ptr->mask > rhs.ptr->mask)
return false;
if(lhs.ptr -> a < rhs.ptr->a)
return true;
if(lhs.ptr->a > rhs.ptr->a)
return false;
return lhs.ptr->b < rhs.ptr->b;
}
};
vector<likeatree *> treeVector;
deque<bool> stdDeque(3);
vector<vector<bool>> boolMatrix{{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};
set<weighted_pointer,ptrcomp> stdSet;
int main(){
srand(time(NULL));
likeatree * first_pointer = new likeatree{0,&input[0],nullptr};
likeatree * second_pointer = first_pointer;
unique_ptr<likeatree> tmp(first_pointer);
weighted_pointer wp;
wp.weight = 1;
wp.pointer = move(tmp);
stdSet.insert(move(wp));
// I'd like to do it inline(or more but with variables that end of scope here), but this don't work. (And i don't keep a copy of the pointer)
// stdSet.insert(move(weighted_pointer{1,move(make_unique<likeatree>(*new likeatree{0,&input[0],nullptr}))}));
return 0;
}
编辑:更改了代码中的一个问题案例
编辑:已解决。使用 make_unique.
时缺少取消引用
你的 weighted_pointer
是不可复制的,因为它包含一个不可复制的成员(unique_ptr
),所以你必须通过 const 引用传递给你的比较函数。
bool operator()(const weighted_pointer& lhs, const weighted_pointer& rhs)
这是因为如果您按值传递它(如当前所写),它将尝试创建函数本地副本。
您也不能这样做,因为您正在尝试复制 tmp
,正如我刚才所说,struct
是不可复制的。
for(unsigned int i = 0; i < stdDeque.size(); i++){
tmp.ptr.reset(new likeatree{0,&stdDeque[i],nullptr});
stdSet.insert(tmp);
}
您可以使用 emplace
就地构建 weighted_pointer
for(unsigned int i = 0; i < stdDeque.size(); i++){
stdSet.emplace(1, std::make_unique<likeatree>(0,&stdDeque[i],nullptr));
}
你的结构在这里:
struct weighted_pointer{
mutable int weight;
unique_ptr<likeatree> ptr;
};
包含一个 std::unique_ptr
。一个std::unique_ptr
无法复制,所以你的整个weighted_pointer
也无法复制。
您的代码中有三个地方您试图复制它,这会导致您看到错误:
bool operator()(const weighted_pointer lhs, const weighted_pointer rhs) {
必须是:
bool operator()(weighted_pointer const& lhs, weighted_pointer const& rhs) {
stdSet.insert(tmp);
这在理论上可以通过以下方式解决:
stdSet.insert(std::move(tmp));
但是,您不能再使用 tmp
,您不仅在同一个循环中而且在下面的循环中都这样做了。所以你必须找到一个完全不同的解决方案。也许使用 emplace
。或者完全重构您的代码。
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer temp){ return temp.ptr.get() == treeVector[i]; });
必须是:
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer const& temp){ return temp.ptr.get() == treeVector[i]; });
对于 VC++ 2013,std::move
修复是不够的。您必须向结构添加一个显式移动构造函数:
struct weighted_pointer{
mutable int weight;
unique_ptr<likeatree> ptr;
weighted_pointer() = default;
weighted_pointer(weighted_pointer&& src) :
weight(std::move(src.weight)),
ptr(std::move(src.ptr))
{
}
};
VC++ 2015 修复了这个问题。更多信息:Default Move Constructor in Visual Studio 2013 (Update 3)
当我编译上面的代码时,编译器说:
In file included from /usr/include/c++/4.8/algorithm:62:0,
from 31791982.cpp:7:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘_InputIterator std::__find_if(_InputIterator, _InputIterator, _Predicate, std::input_iterator_tag) [with _InputIterator = std::_Rb_tree_const_iterator<weighted_pointer>; _Predicate = main()::__lambda0]’:
/usr/include/c++/4.8/bits/stl_algo.h:4465:41: required from ‘_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = std::_Rb_tree_const_iterator<weighted_pointer>; _Predicate = main()::__lambda0]’
31791982.cpp:55:124: required from here
看看第 55 行 - 发生了什么:
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer temp){ return temp.ptr.get() == treeVector[i]; });
我们正在尝试将数组中的 weighted_pointer
复制到 lambda 的 temp
中。但实际上,我们对 const ref 很满意,所以用 const weighted_pointer&
替换并再次编译:
/usr/include/c++/4.8/bits/stl_tree.h: In instantiation of ‘std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Key = weighted_pointer; _Val = weighted_pointer; _KeyOfValue = std::_Identity<weighted_pointer>; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = weighted_pointer]’:
/usr/include/c++/4.8/bits/stl_tree.h:1377:47: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = const weighted_pointer&; _Key = weighted_pointer; _Val = weighted_pointer; _KeyOfValue = std::_Identity<weighted_pointer>; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>]’
/usr/include/c++/4.8/bits/stl_set.h:463:29: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const value_type&) [with _Key = weighted_pointer; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<weighted_pointer>; std::set<_Key, _Compare, _Alloc>::value_type = weighted_pointer]’
31791982.cpp:49:26: required from here
第 49 行是:
stdSet.insert(tmp);
我们无法将 tmp
复制到集合中。如果我们不打算重新使用 tmp
,我们可以改为移动它:
for(unsigned int i = 0; i < stdDeque.size(); i++){
weighted_pointer tmp;
tmp.weight = 1;
tmp.ptr.reset(new likeatree{0,&stdDeque[i],nullptr});
stdSet.insert(std::move(tmp));
}
然后我们就可以轻松修复 ptrcomp::operator()
,它需要通过 const 引用接受其参数。
我遇到了很多使用已删除函数的错误。我只是将 weighted_pointer
的指针更改为 unique_ptr
。但是我不明白为什么会出现错误,有什么提示吗?
likeatree
是一个DAG结构,可以根据掩码值指向另一个结构或stdDeque
的元素。
weighted_pointer
的 weight
有 mutable
关键字,因为不会改变集合中的位置。
#include <deque>
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>
#include <memory>
#include <chrono>
using namespace std;
struct likeatree{
unsigned int mask : 3;
void * a;
void * b;
};
struct weighted_pointer{
mutable int weight;
unique_ptr<likeatree> ptr;
};
struct ptrcomp{
bool operator()(const weighted_pointer & lhs, const weighted_pointer & rhs) {
if(lhs.ptr->mask < rhs.ptr->mask)
return true;
if(lhs.ptr->mask > rhs.ptr->mask)
return false;
if(lhs.ptr -> a < rhs.ptr->a)
return true;
if(lhs.ptr->a > rhs.ptr->a)
return false;
return lhs.ptr->b < rhs.ptr->b;
}
};
vector<likeatree *> treeVector;
deque<bool> stdDeque(3);
vector<vector<bool>> boolMatrix{{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};
set<weighted_pointer,ptrcomp> stdSet;
int main(){
srand(time(NULL));
likeatree * first_pointer = new likeatree{0,&input[0],nullptr};
likeatree * second_pointer = first_pointer;
unique_ptr<likeatree> tmp(first_pointer);
weighted_pointer wp;
wp.weight = 1;
wp.pointer = move(tmp);
stdSet.insert(move(wp));
// I'd like to do it inline(or more but with variables that end of scope here), but this don't work. (And i don't keep a copy of the pointer)
// stdSet.insert(move(weighted_pointer{1,move(make_unique<likeatree>(*new likeatree{0,&input[0],nullptr}))}));
return 0;
}
编辑:更改了代码中的一个问题案例 编辑:已解决。使用 make_unique.
时缺少取消引用你的 weighted_pointer
是不可复制的,因为它包含一个不可复制的成员(unique_ptr
),所以你必须通过 const 引用传递给你的比较函数。
bool operator()(const weighted_pointer& lhs, const weighted_pointer& rhs)
这是因为如果您按值传递它(如当前所写),它将尝试创建函数本地副本。
您也不能这样做,因为您正在尝试复制 tmp
,正如我刚才所说,struct
是不可复制的。
for(unsigned int i = 0; i < stdDeque.size(); i++){
tmp.ptr.reset(new likeatree{0,&stdDeque[i],nullptr});
stdSet.insert(tmp);
}
您可以使用 emplace
就地构建 weighted_pointer
for(unsigned int i = 0; i < stdDeque.size(); i++){
stdSet.emplace(1, std::make_unique<likeatree>(0,&stdDeque[i],nullptr));
}
你的结构在这里:
struct weighted_pointer{ mutable int weight; unique_ptr<likeatree> ptr; };
包含一个 std::unique_ptr
。一个std::unique_ptr
无法复制,所以你的整个weighted_pointer
也无法复制。
您的代码中有三个地方您试图复制它,这会导致您看到错误:
bool operator()(const weighted_pointer lhs, const weighted_pointer rhs) {
必须是:
bool operator()(weighted_pointer const& lhs, weighted_pointer const& rhs) {
stdSet.insert(tmp);
这在理论上可以通过以下方式解决:
stdSet.insert(std::move(tmp));
但是,您不能再使用 tmp
,您不仅在同一个循环中而且在下面的循环中都这样做了。所以你必须找到一个完全不同的解决方案。也许使用 emplace
。或者完全重构您的代码。
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer temp){ return temp.ptr.get() == treeVector[i]; });
必须是:
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer const& temp){ return temp.ptr.get() == treeVector[i]; });
对于 VC++ 2013,std::move
修复是不够的。您必须向结构添加一个显式移动构造函数:
struct weighted_pointer{
mutable int weight;
unique_ptr<likeatree> ptr;
weighted_pointer() = default;
weighted_pointer(weighted_pointer&& src) :
weight(std::move(src.weight)),
ptr(std::move(src.ptr))
{
}
};
VC++ 2015 修复了这个问题。更多信息:Default Move Constructor in Visual Studio 2013 (Update 3)
当我编译上面的代码时,编译器说:
In file included from /usr/include/c++/4.8/algorithm:62:0,
from 31791982.cpp:7:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘_InputIterator std::__find_if(_InputIterator, _InputIterator, _Predicate, std::input_iterator_tag) [with _InputIterator = std::_Rb_tree_const_iterator<weighted_pointer>; _Predicate = main()::__lambda0]’:
/usr/include/c++/4.8/bits/stl_algo.h:4465:41: required from ‘_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = std::_Rb_tree_const_iterator<weighted_pointer>; _Predicate = main()::__lambda0]’
31791982.cpp:55:124: required from here
看看第 55 行 - 发生了什么:
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer temp){ return temp.ptr.get() == treeVector[i]; });
我们正在尝试将数组中的 weighted_pointer
复制到 lambda 的 temp
中。但实际上,我们对 const ref 很满意,所以用 const weighted_pointer&
替换并再次编译:
/usr/include/c++/4.8/bits/stl_tree.h: In instantiation of ‘std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Key = weighted_pointer; _Val = weighted_pointer; _KeyOfValue = std::_Identity<weighted_pointer>; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = weighted_pointer]’:
/usr/include/c++/4.8/bits/stl_tree.h:1377:47: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = const weighted_pointer&; _Key = weighted_pointer; _Val = weighted_pointer; _KeyOfValue = std::_Identity<weighted_pointer>; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>]’
/usr/include/c++/4.8/bits/stl_set.h:463:29: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const value_type&) [with _Key = weighted_pointer; _Compare = ptrcomp; _Alloc = std::allocator<weighted_pointer>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<weighted_pointer>; std::set<_Key, _Compare, _Alloc>::value_type = weighted_pointer]’
31791982.cpp:49:26: required from here
第 49 行是:
stdSet.insert(tmp);
我们无法将 tmp
复制到集合中。如果我们不打算重新使用 tmp
,我们可以改为移动它:
for(unsigned int i = 0; i < stdDeque.size(); i++){
weighted_pointer tmp;
tmp.weight = 1;
tmp.ptr.reset(new likeatree{0,&stdDeque[i],nullptr});
stdSet.insert(std::move(tmp));
}
然后我们就可以轻松修复 ptrcomp::operator()
,它需要通过 const 引用接受其参数。