首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++删除函数错误的使用

C++删除函数错误的使用
EN

Stack Overflow用户
提问于 2015-08-03 16:09:46
回答 3查看 30.8K关注 0票数 4

我得到了很多使用删除的函数错误。我刚刚更改了weighted_pointerunique_ptr的指针。但我不知道为什么我会犯错,有什么建议吗?

likeatree是一个DAG结构,它可以基于掩码值指向另一个结构或stdDeque的一个元素。

weight of weighted_pointermutable关键字,因为集合中的位置不会改变。

代码语言:javascript
运行
复制
#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时缺少取消引用。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-08-03 16:36:52

你在这里的结构:

结构weighted_pointer{可变整权;unique_ptr ptr;};

包含一个std::unique_ptrstd::unique_ptr不能被复制,所以您的整个weighted_pointer也不能复制。

在您的代码中有三个地方试图复制它,这会导致您看到的错误:

布尔算子()( const weighted_pointer lhs,const weighted_pointer rhs) {

必须:

代码语言:javascript
运行
复制
bool operator()(weighted_pointer const& lhs, weighted_pointer const& rhs) {

stdSet.insert(tmp);

从理论上讲,这可以通过以下方式加以解决:

代码语言:javascript
运行
复制
stdSet.insert(std::move(tmp));

但是,您就不能再使用tmp了,不仅在相同的循环中,而且在下面的循环中也是如此。所以你必须找到一个完全不同的解决方案。也许可以使用emplace。或者完全重构您的代码。

auto it = find_if(stdSet.begin(),stdSet.end(),&{返回temp.ptr.get() == treeVectori;});

必须:

代码语言:javascript
运行
复制
auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer const& temp){ return temp.ptr.get() == treeVector[i]; });

对于VC++ 2013,std::move修复是不够的。您必须向您的结构中添加一个显式移动构造函数:

代码语言:javascript
运行
复制
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)

票数 9
EN

Stack Overflow用户

发布于 2015-08-03 16:15:21

您的weighted_pointer是不可复制的,因为它包含一个不可复制的成员( unique_ptr),因此您必须通过const引用将它传递给您的比较器函数。

代码语言:javascript
运行
复制
bool operator()(const weighted_pointer& lhs, const weighted_pointer& rhs)

这是因为如果您按值传递它(就像当前编写的那样),它将尝试创建一个函数--本地副本。

您也不能这样做,因为您正在试图复制tmp,正如我刚才所说的,struct是不可复制的。

代码语言:javascript
运行
复制
for(unsigned int i = 0; i < stdDeque.size(); i++){
    tmp.ptr.reset(new likeatree{0,&stdDeque[i],nullptr});
    stdSet.insert(tmp);
}

您可以使用emplace就地构造weighted_pointer

代码语言:javascript
运行
复制
for(unsigned int i = 0; i < stdDeque.size(); i++){
    stdSet.emplace(1, std::make_unique<likeatree>(0,&stdDeque[i],nullptr));
}
票数 4
EN

Stack Overflow用户

发布于 2015-08-03 16:55:21

当我编译上面的代码时,编译器说:

代码语言:javascript
运行
复制
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行发生了什么

代码语言:javascript
运行
复制
    auto it = find_if(stdSet.begin(),stdSet.end(),[&](weighted_pointer temp){ return temp.ptr.get() == treeVector[i]; });

我们正在尝试将一个weighted_pointer从数组复制到lambda的temp中。但实际上,我们很乐意使用const,所以用const weighted_pointer&替换,然后再编译一次:

代码语言:javascript
运行
复制
/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行是:

代码语言:javascript
运行
复制
    stdSet.insert(tmp);

我们不能把tmp拷贝到片场里。如果我们不打算重复使用tmp,我们可以移动它:

代码语言:javascript
运行
复制
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引用来接受它的参数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31791982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档