【问题标题】:find_if error: invalid initialisation of reference of type 'const node&' from expression of type 'node*'find_if 错误:从“node*”类型的表达式中对“const node&”类型的引用无效初始化
【发布时间】:2015-01-26 19:39:28
【问题描述】:

我有一个结构节点:

struct node {
    node *parent;
    int x, y;
    float f, g, h;
    };

我定义了一个谓词条件 bool 函数如下来查找向量中是否已经存在结构成员。

bool Isinit(const node &nm, const node &ref)
{
  if(nm.x==ref.x && nm.y==ref.y)
    return true;
  else
    return false;
}

然后我这样调用函数:

vector<node*>::iterator referIt=find_if (open.begin(), open.end(), Isinit);

报错: 从“node*”类型的表达式中对“const node&”类型的引用进行无效初始化。有人可以向我解释这个错误吗?

【问题讨论】:

  • if (…) return true; else return false; 是一个糟糕的反模式。改写return …;,逻辑上等价,可读性更强。

标签: c++ algorithm vector function-pointers


【解决方案1】:

您的代码存在两个问题:参数数量和参数类型:

vector<node*>::iterator referIt = 
    find_if (open.begin(), open.end(), Isinit);

bool Isinit(const node &nm, const node &ref);

find_if 采用 一元 谓词。它将在每个元素上调用它,直到找到谓词为其返回 true 的元素。该谓词必须接受容器中类型的 one 参数。从您对find_if 的呼叫中,该类型为node*。因此,您的签名必须是:

bool Isinit(const node* nm);

现在这可能无法满足您想要做的事情,因为您正在寻找一个 node* 来匹配您的 ref,因此您需要编写一个仿函数:

struct Isinit {
    const node* ref;

    Isinit(const node*);
    bool operator()(const node* nm); // compare passed-in 'nm'
                                     // against member 'ref'
};

然后这样称呼:

vector<node*>::iterator referIt = 
    find_if (open.begin(), open.end(), Isinit(ref));

使用 C++11 的 lambda,都可以在线完成:

auto referIt = find_if(open.begin(), open.end(), [ref](const node* nm){
    return nm->x == ref->x && nm->y == ref->y;
});

【讨论】:

  • 您能详细说明仿函数方法吗?据我所知,仿函数具有构造函数和重载运算符。那么你是如何在这里定义构造函数的呢?您将如何使用这种方法返回node*?
  • @userzizzy 函子就是任何带有operator() 的东西。我没有定义构造函数 - 但它应该只需要一个 node* 并将成员 ref 分配给它。没有返回 node* - 它应该返回 bool。
【解决方案2】:

这是来自cppreference.com 的find_if 的可能实现:

template<class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
{
    for (; first != last; ++first) {
        if (p(*first)) {
            return first;
        }
    }
    return last;
}

您似乎拥有node* 中的vector,因此,当您迭代和取消引用迭代器时,您传递给p 的是node*,而不是node&amp; 元素。您可以更改您的函数以接受指针来解决此问题。另外,请注意 find_if 实现接受 UnaryPredicate p,因此您不能将接受两个参数的函数传递给它。

编辑:

解决此问题的另一种C++11 方法是使用functional 标头中的bind 并将ref 绑定到Isinit 为:

using namespace std::placeholders;
auto referIt = find_if (open.begin(), open.end(), std::bind(Isinit, _1, &ref));

【讨论】:

  • 你的意思是:bool Isinit(const node* nm, const node* ref)?这给了error: too few arguments to function。
  • 正确,但find_if 还需要一个一元谓词而不是二元谓词,因此您不能以这种方式将两个东西传递给它。应该是bool Isinit(const node *nm)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多