You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用std::thread创建线程时触发“invalid use of void expression”编译错误的求助(TCP Socket通信场景)

问题:TCP Socket传输代码中std::thread构造时触发"invalid use of void expression"错误

我正在尝试不依赖Boost库,用C++实现客户端与服务器的TCP数据传输,但编译时遇到了两个错误。以下是我的代码实现和编译错误信息:

Server类的SendXBytes方法实现

void Server::SendXBytes(int socket, unsigned int x, void* buffer) {
    int bytesSent = 0;
    int result;
    int* bufferint = (int*)buffer;
    while (bytesSent < x) {
        result = read(socket, bufferint + bytesSent, x - bytesSent);
        if (result < 1) {
            cout << "Error sending bytes" << endl;
        }
    }
}

main.cpp中的调用代码

#include "client.cpp"
#include "server.cpp"
#include <thread>
int main() {
    int server_id;
    int socket;
    Server server(1024);
    Client client(1024);
    int server_fd = server.createSocket(server_id);
    server.PrepareSocket(server_fd);
    server.AcceptConn(server_fd, socket);
    int* buffer = new int[2000];
    std::thread client_th(client.SendXBytes(socket, 512, (void*)buffer));
    std::thread server_th(server.ReadXBytes(socket, 512, (void*)buffer));
    server_th.join();
    client_th.join();
}

编译错误信息

main.cpp:15:70: error: invalid use of void expression
std::thread server_th(server.ReadXBytes(socket, 512, (void*)buffer));
^
main.cpp:16:70: error: invalid use of void expression
std::thread client_th(client.SendXBytes(socket, 512, (void*)buffer));

我尝试了一些方法但没解决,希望得到帮助。


解决方案

1. 错误根源:错误的std::thread构造方式

你遇到的错误是因为你直接调用了返回void的成员函数,把函数执行后的void结果传给了std::thread的构造函数——而std::thread需要的是一个可调用对象(比如函数指针、lambda、绑定后的函数)加上对应的参数,不是直接执行函数的结果。

2. 两种修复方式

方式一:使用Lambda表达式(最直观易读)

用lambda包裹你的成员函数调用,这样std::thread会把lambda作为可执行对象来运行:

int main() {
    // ... 其他代码保持不变 ...
    int* buffer = new int[2000];
    // 用lambda包裹成员函数调用
    std::thread server_th([&](){ 
        server.ReadXBytes(socket, 512, (void*)buffer); 
    });
    std::thread client_th([&](){ 
        client.SendXBytes(socket, 512, (void*)buffer); 
    });
    server_th.join();
    client_th.join();
    delete[] buffer; // 别忘了释放内存!
}

这里的[&]是捕获当前作用域的所有引用,确保lambda能访问到server、client、socket和buffer变量。因为你后面调用了join(),这些变量的生命周期会覆盖线程运行时间,所以不会有悬空引用的问题。

方式二:使用std::bind绑定成员函数

如果你更习惯用std::bind,可以把成员函数和对象实例绑定起来,作为可调用对象传给std::thread:

#include <functional> // 必须包含这个头文件

int main() {
    // ... 其他代码保持不变 ...
    int* buffer = new int[2000];
    std::thread server_th(
        std::bind(&Server::ReadXBytes, &server, socket, 512, (void*)buffer)
    );
    std::thread client_th(
        std::bind(&Client::SendXBytes, &client, socket, 512, (void*)buffer)
    );
    server_th.join();
    client_th.join();
    delete[] buffer;
}

注意:成员函数的第一个绑定参数必须是对象的指针(&server、&client),因为成员函数需要依赖对象实例才能调用。

3. 额外的逻辑错误提醒

你的Server::SendXBytes方法里有个明显的笔误:你用了read()函数(这是从socket读取数据),但方法名是SendXBytes(应该发送数据)!这会导致你的发送逻辑完全错误,应该改成send()函数,同时还要修正缓冲区的类型(用char*比int*更合适,避免数据对齐问题):

#include <iostream>
#include <sys/socket.h> // 确保包含send/read的头文件
#include <string.h> // 用于strerror

void Server::SendXBytes(int socket, unsigned int x, void* buffer) {
    int bytesSent = 0;
    int result;
    char* bufferChar = static_cast<char*>(buffer);
    while (bytesSent < x) {
        result = send(socket, bufferChar + bytesSent, x - bytesSent, 0);
        if (result < 0) { // send返回-1表示错误,0表示连接已关闭
            std::cerr << "Error sending bytes: " << strerror(errno) << std::endl;
            break; // 错误发生后退出循环,避免死循环
        }
        bytesSent += result;
    }
}

同样,你的ReadXBytes方法也应该用类似的逻辑,正确处理read()的返回值,避免死循环或错误。

内容的提问来源于stack exchange,提问作者Math Lover

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 00:43:12