【问题标题】:std::thread error: invalid use of void expressionstd::thread 错误:无效表达式的使用
【发布时间】:2021-11-09 11:53:06
【问题描述】:

我必须使用套接字(不使用 boost 库)从客户端向服务器发送数据(通过 TCP)。

我在 cpp 文件中的实现:

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));

我尝试了一些解决方案,但仍然有同样的错误....

【问题讨论】:

  • 带有int 数组的名称bytesSent 很奇怪。另外,我会避免裸露new,并在可能的情况下进行类型转换
  • std::thread 的构造函数接受的参数是一个函数(或函数对象),并且可以选择传递给该函数的一组参数。线程本身将调用该函数。没有构造函数接受调用函数的结果(除非该函数返回指向函数或函数对象的指针,而您的函数调用不会)但这就是 main() 传递的内容。试试std::thread client_th(&amp;Server::SendXBytes, &amp;client, socket, 512, (void *)buffer);
  • 顺便说一句,你打电话给read而不是write
  • 您真的不想在线程之间共享缓冲区。 (为什么ClientServer 不管理自己的缓冲区?)
  • @user253751,是的,你是对的......!

标签: c++ void


【解决方案1】:
std::thread client_th(client.SendXBytes(socket, 512, (void*)buffer));

这直接调用SendXBytes函数,将其返回值(即void)传递给std::thread构造函数,导致错误。您可能打算做的是将调用包装在 lambda 中,如下所示:

std::thread client_th([&]{ client.SendXBytes(socket, 512, (void*)buffer); });

如果您从未听说过 lambda,您也许可以阅读它们。确保您了解通过引用(如此处)或使用= 而不是&amp; 通过值捕获外部变量的含义。在这种情况下,可以通过引用来捕获,但如果线程可能比捕获的变量寿命更长,则会导致未定义的行为。

【讨论】:

  • 这里无需引用捕获。如果要调用非const 方法,可以按值捕获并声明lambda mutable
  • @PaulSanders 我通常通过引用作为默认值,因为它可以避免潜在的昂贵副本。不过在这种情况下两者都可以。
  • 实际上,我们不知道clientserver 是什么。很有可能它们甚至无法复制。
  • 似乎std::thread client_th(&amp;Client::SendXBytes, &amp;client, socket, 512, (void*)buffer); 将是可复制“问题”的可接受解决方案。还避免使用 lambda(和捕获语义),这为 C++ 新手提供了一些学习曲线。
  • @Possseidon 复制this 很便宜。
猜你喜欢
  • 1970-01-01
  • 2014-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
  • 2012-09-03
  • 1970-01-01
相关资源
最近更新 更多