c++ 存储空函数指针和要传递给回调的参数

pnwntuvh  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(141)

我正在研究一个C++的算法,它可以像线性结构一样对列表进行排序,而不需要任何外部数据结构的帮助。我的计划是先找到最小值,然后将其放在开始处,开始比较和排序其余的值。我没有使用STL,因为我试图了解这门语言的基础。这种学习方法代表了我旅程中的一条较长的道路,但我认为它是一个很好的学习方法。我做这件事感觉很好。
我的计划是使用iterate函数作为主函数,通过我的线性结构调用以下辅助函数:print用于查看控制台中的值,getLast用于添加节点,findMin用于查找开始的最小值。我读过一些关于std::function相关问题的堆栈溢出答案,lambda表达式和函数指针。在某些时候,我对这么多的信息感到困惑,然后意识到最简单但最有效的方法是依靠函数指针。尝试在void(*callback)(Node* node)中存储对函数的引用会引发无法找到函数地址的错误。

void List::iterate(Node * node,void(*callBack)(Node* node)){
  callBack(node);
  if(node->next == nullptr)
    return;
  iterate(node->next,callBack); 
}

void List::add(int data){
  void (*callback)(Node* node) = &print(root); //Can't take the address of an rvalue of type void 
  iterate(root, callBack);
}

我在互联网上找到的东西很难应用到我的代码中,原因有两个。一个是示例有一个返回值类型,没有参数,第二个是大多数示例都不在类中。第二个原因导致了非静态值的问题,特别是当试图使用lambdas和std::function时。
我想问一下社区,void函数是否有特殊的处理方式。另外,我的猜测是,有返回值的函数更容易处理,因为类型代表了编译时可以分配的内存大小,而void显然是未知的。这背后的理论是什么?同时,我将阅读这篇Stack Overflow post what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues,以更好地理解控制台告诉我的内容。
有谁能告诉我我的代码做错了什么吗?我错过了什么概念/没有很好地应用到练习中?另外,如果你觉得你需要对代码给予额外的反馈,请这样做,我也非常感激。
这是练习

/* Implement sorting in a dynamic linked list without using an additional array or data structure.*/

#include <iostream>

class List{
  struct Node{
    int data;
    Node* next = nullptr;
  };
  public:
    List(int data);
    ~List();
    void add(int data);
    void iterate(Node * node, void(*callback)(Node* node));
  private:
    void print(Node *node);
    void findMin(Node* node);
    void getLast(Node* node);
    int min = 0;
    Node* root = new Node;
    Node* it;
};

List::List(int data){
  root->data = data;
  it = root;
}

List::~List(){}

void List::print(Node *node){
  std::cout<<node->data<<'\n';
}

void List::findMin(Node* node){
  if (node->data<min) {
    min = node->data; 
  }
}

void List::getLast(Node* node){
  it = node; 
}

void List::iterate(Node * node,void(*callBack)(Node* node)){
  callBack(node);
  if(node->next == nullptr)
    return;
  iterate(node->next,callBack); 
}

void List::add(int data){
  void (*callback)(Node* node) = &print(root); //Can't take the address of an rvalue of type void 
  iterate(root, callBack);
}

int main(){
  List list(8); 
  list.add(9);
  list.add(7);
  list.add(4);
  list.add(3);

  return 0;
}

【进展】
很高兴能读到那些stackoverflow成员的评论,他们及时为我的问题做出了贡献。我现在正在处理Igor Tandetnik的评论,这不仅仅是复制粘贴他的片段,而是阅读他们为什么工作,以了解何时以及如何使用它们以供将来参考。我将很快发布解决方案。
[编辑]
按照PaulMcKenzie的建议,在类声明中使用new Node初始化root

wgxvkvu9

wgxvkvu91#

这个答案归功于Igor Tandetnik。当试图将函数存储为std::function而不使用lambda表达式时,非静态异常绝对误导了我找到答案。然后我选择用一个函数指针来找到答案,这让我无处可去。
这是List::add(int data)方法中建议的lambda表达式的示例。

void List::add(int data){
  callback = [this](Node* node){getLast(node);}
  iterate(root,callback);
  it->next = new Node;
  it->next->data = data;
}

相关问题