使用std::thread创建线程时触发“invalid use of void expression”编译错误的求助(TCP Socket通信场景)
我正在尝试不依赖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

