chaaaa1 2022-07-05 16:13 采纳率: 100%
浏览 49
已结题

void*func 需要return么

问题遇到的现象和发生背景

编译时 void*func 报错说没有返回值

问题相关代码,请勿粘贴截图

#include
#include <unistd.h>
#include "threadpoolV3.h"

#include <iostream>
#include <unistd.h>
#include "threadpoolV3.h"
class Job
{
public:
    Job(){}
    Job(int *a)
    {
        arg = new int(*a);
    }
    // 发给线程的回调函数
    void *func()
    {
        printf("%d\n", *arg);
        return ;
    }
    ~Job()
    {
        delete arg;
    }
private:
    int *arg;
};

int main()
{
    // 创建一个线程池对象,线程数量4,任务队列长度为20
    ThreadPool<Job> *pool = new ThreadPool<Job>(4,20);
    printf("线程池创建成功\n");
    int i;
    Job *newjob;
    for(i = 0;i<100;++i)
    {
        newjob = new Job(&i);
        pool->append(newjob);
        
    }
    printf("end\n");
    pthread_exit(NULL); // 主线程结束
    return 0;
}



// 封装一个【线程池】类
#ifndef __THREADPOOLV3_H__
#define __THREADPOOLV3_H__

// 导入头文件
#include <queue>
#include <stdio.h>
#include <semaphore.h>
// 类内声明,类外定义
template <typename T>
class ThreadPool
{
public:
    // 构造函数
    ThreadPool(unsigned int t_nums, unsigned int j_nums);

    // 析构函数
    ~ThreadPool();

    // 成员函数:往线程池中【添加】任务事件
    bool append(T *newjob);

private:
    // 核心线程的数量
    unsigned int m_thread_num;
    // 最大线程的数量
    unsigned int m_thread_max;
    // 任务队列长度
    unsigned int m_queue_len;
    // 工作队列(存放线程的)
    pthread_t *m_work_threads; // 用动态数组实现
    // 任务队列(存放线程需要执行的任务《函数》的)
    std::queue<T *> m_job_queue;
    // 用queue,list,数组实现都行
    // 线程的回调函数
    static void *worker(void *arg);
    void m_run();          // worker的封装函数
    void m_add(T *newjob); // append的封装函数
    // 线程同步机制
    sem_t sem_job_src;   // 任务队列资源的个数
    sem_t sem_job_empty; //任务队列空闲位置的个数
    sem_t sem_mutex;     // 互斥锁信号量
    // 设置一个标志位,表示整个线程池是否在进行中
    bool isRun;
};

/********************** 以下全是类的定义 **********************/
// 构造函数
template <typename T>
ThreadPool<T>::ThreadPool(unsigned int t_nums, unsigned int j_nums)
{
    // 初始化线程数量等成员变量
    // 判断输入数据的合法性
    if (t_nums <= 0 || j_nums <= 0)
    {
        printf("参数传入错误\n");
        throw std::exception();
    }
    m_thread_num = t_nums;
    m_queue_len = j_nums;
    // 初始化信号量,表示job队列资源的信号量不变,互斥锁的信号量初始化为1
    sem_init(&sem_job_src, 0 , 0);
    sem_init(&sem_job_empty, 0, m_queue_len);
    sem_init(&sem_mutex, 0, 1);
    // 初始化线程池状态
    isRun = true;
    // 申请堆区内存,存放子线程的线程号
    m_work_threads = new pthread_t[m_thread_num];
    if (!m_work_threads)
    {
        // 如果开辟堆区动态内存失败,抛出异常
        isRun = false;
        printf("堆区开辟内存失败\n");
        throw std::exception();
    }
    // 创建 m_thread_num 个子线程
    for (int i = 0; i < m_thread_num; ++i)
    {
        int ret;
        ret = pthread_create(m_work_threads + i, NULL, worker, this);
        if (ret != 0)
        {
            // 创建线程出现异常,终止整个程序,清除资源
            delete[] m_work_threads;
            isRun = false;
            printf("创建线程失败\n");
            throw std::exception();
        }
    }
    // 线程创建后,设置线程分离
    for (int i = 0; i < m_thread_num; ++i)
    {
        int ret;
        ret = pthread_detach(m_work_threads[i]);
        if (ret != 0)
        {
            // 创建线程出现异常,终止整个程序,清除资源
            delete[] m_work_threads;
            isRun = false;
            printf("线程分离失败\n");
            throw std::exception();
        }
    }
}
// 析构函数
template <typename T>
ThreadPool<T>::~ThreadPool()
{
    // 销毁指针,释放堆区内存等
    delete[] m_work_threads;
    isRun = false;
}
// public成员函数:append
template <typename T>
bool ThreadPool<T>::append(T *newjob)
{
    printf("添加任务\n");
    m_add(newjob);
    return true;
}
template <typename T>
void ThreadPool<T>::m_add(T *newjob)
{
    // 往内存池中,添加一个工作事件,事件应该被添加到任务队列中
    // 在主线程中,向任务队列中写入数据,必须要加锁
    // 上互斥锁
    // 用信号量判断job队列是否还有空间
    sem_wait(&sem_job_empty); // 工作队列满了,阻塞在此
    sem_wait(&sem_mutex);

    m_job_queue.push(newjob);

    sem_post(&sem_mutex);   // 解锁
    sem_post(&sem_job_src); // job资源的信号量加1
}
// private成员函数:m_run
template <typename T>
void *ThreadPool<T>::worker(void *arg)
{
    // 内存池中的线程,需要执行的任务,任务从任务队列中取
    // 从任务队列中取出一个任务,从工作队列(线程s)中取出一个线程,让线程去执行这个任务(函数)
    // 任务的形态应该是什么:
    // 《函数》
    // 其实本质上,仍旧是生产者和消费者模型
    printf("执行工作任务\n");
    ThreadPool *pool = (ThreadPool *)arg;
    pool->m_run();
    return NULL;
}
template <typename T>
void ThreadPool<T>::m_run()
{
    while (isRun)
    {
        // 消耗一个资源,如果任务队列没有资源,阻塞等待(就相当于是让线程睡眠了)
        sem_wait(&sem_job_src);
        sem_wait(&sem_mutex); // 互斥锁

        // 取出一个任务
        T *Newjob = m_job_queue.front();
        m_job_queue.pop();

        // 退出,解锁
        sem_post(&sem_mutex);
        sem_post(&sem_job_empty);

        // 拿到job后,在锁外执行job内具体的函数
        printf("线程成功获取任务\n");
        Newjob->func();
    }
}
#endif
运行结果及报错内容

h@ubuntu:~/workspace/niuke/xianchengchi$ g++ -o test2.out test2.cpp -lpthread
test2.cpp: In member function ‘void* Job::func()’:
test2.cpp:18:5: warning: no return statement in function returning non-void [-Wreturn-type]
   18 |     }
      |     ^
我的解答思路和尝试过的方法
我想要达到的结果
  • 写回答

2条回答 默认 最新

  • 快乐鹦鹉 2022-07-05 16:14
    关注

    需要return一个指针,什么类型都可以的
    void表示无返回值,可以不返回
    void *表示需要返回一个无类型的指针对象,必须返回
    你这输出函数用void就可以了啊,干嘛要用指针

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 7月16日
  • 已采纳回答 7月8日
  • 创建了问题 7月5日

悬赏问题

  • ¥30 酬劳2w元求合作写文章
  • ¥15 在现有系统基础上增加功能
  • ¥15 远程桌面文档内容复制粘贴,格式会变化
  • ¥15 关于#java#的问题:找一份能快速看完mooc视频的代码
  • ¥15 这种微信登录授权 谁可以做啊
  • ¥15 请问我该如何添加自己的数据去运行蚁群算法代码
  • ¥20 用HslCommunication 连接欧姆龙 plc有时会连接失败。报异常为“未知错误”
  • ¥15 网络设备配置与管理这个该怎么弄
  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图