Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;函数声明和对象初始化之间的区别_C++_C++11 - Fatal编程技术网

C++ C++;函数声明和对象初始化之间的区别

C++ C++;函数声明和对象初始化之间的区别,c++,c++11,C++,C++11,如果我写了这行代码: std::thread t(EchoServer(socket)); 编译器如何解释此指令?它可以是函数声明,也可以只是初始化。 我有以下代码: #include <iostream> #include <thread> #include <boost/asio.hpp> #include <boost/asio.hpp> typedef boost::asio::ip::tcp::socket Socket; auto

如果我写了这行代码:

std::thread t(EchoServer(socket));
编译器如何解释此指令?它可以是函数声明,也可以只是初始化。 我有以下代码:

#include <iostream>
#include <thread>
#include <boost/asio.hpp>

#include <boost/asio.hpp>

typedef boost::asio::ip::tcp::socket Socket;
auto socket_deleter = [] (Socket* s) {s->close(); delete s;};
typedef std::unique_ptr<Socket, decltype(socket_deleter)> socket_ptr;

class EchoServer {
public:
    static void Listen(unsigned int port)
    {

        using namespace std;
        using namespace boost::asio;

        io_service ios;

        // create an endpoint to listen to a certain port
        ip::tcp::endpoint endpoint(ip::tcp::v4(), port);

        cout << "Listening to TCP Socket on port " << port << " ..." << endl;

        // Start opening a socket
        ip::tcp::acceptor acceptor(ios, endpoint);

        // this loop must be infinite... but we accept only 3 connections
        auto socket = socket_ptr(new Socket(ios));

        std::thread t(EchoServer(socket));
    }

    EchoServer(socket_ptr&& s) : m_socket(std::move(s))
    {
    }

    void operator ()() const
    {
    }

private:
    socket_ptr m_socket;
};
那么我如何解释这一行是std::threadcreation类型的对象,而不是函数声明呢

更新1: 我使用的visual studio 2012不支持统一初始化,因此我将代码从
std::thread t((EchoServer(socket)))更改为
std::线程t((EchoServer(套接字))但这次我有一个编译时错误,我不明白:

error C2440: '<function-style-cast>': cannot convert from 'std::unique_ptr<_Ty,_Dx>' to 'EchoServer'
错误C2440:'':无法从'std::unique_ptr'转换为'EchoServer'
我错过了什么

更新2 我可能必须更好地理解移动语义,问题在于socket\u ptr的声明。我以这种(丑陋的)方式更改了代码。。。但现在编译

#include <iostream>
#include <thread>
#include <boost/asio.hpp>

typedef boost::asio::ip::tcp::socket Socket;
auto socket_deleter = [] (Socket* s) {s->close(); delete s;};
/*
typedef std::unique_ptr<Socket, decltype(socket_deleter)> socket_ptr;
*/
typedef Socket* socket_ptr;

class EchoServer {
public:
    static void Listen(unsigned int port)
    {

        using namespace std;
        using namespace boost::asio;

        io_service ios;

        // create an endpoint to listen to a certain port
        ip::tcp::endpoint endpoint(ip::tcp::v4(), port);

        cout << "Listening to TCP Socket on port " << port << " ..." << endl;

        // Start opening a socket
        ip::tcp::acceptor acceptor(ios, endpoint);

        // this loop must be infinite... but we accept only 3 connections
        auto socket = new Socket(ios);

        std::thread t((EchoServer(socket)));
    }

    EchoServer(socket_ptr s) : m_socket(s)
    {
    }

    ~EchoServer()
    {
        m_socket->close();
        delete m_socket;
    }

    void operator ()() const
    {
    }

private:
    socket_ptr m_socket;
};
#包括
#包括
#包括
typedef boost::asio::ip::tcp::socket;
自动套接字删除器=[](套接字*s){s->close();删除s;};
/*
typedef std::唯一的\u ptr插座\u ptr;
*/
类型定义插座*插座ptr;
类EchoServer{
公众:
静态void侦听(无符号int端口)
{
使用名称空间std;
使用名称空间boost::asio;
io_服务ios;
//创建端点以侦听特定端口
ip::tcp::endpoint端点(ip::tcp::v4(),端口);

cout
static\u cast
可用于触发用户定义的转换,请尝试

std::thread t(static_cast<EchoServer>(socket));

这是一个函数声明。如果要通过直接初始化声明对象,可以使用以下方法之一:

std::thread t(EchoServer { socket });
std::thread t { EchoServer(socket) };
std::thread t { EchoServer { socket} };
std::thread t((EchoServer(socket)));

括号初始化是明确的初始化,在最后一行中有括号表达式,它不能作为函数参数声明。

< P>在C++ 2011中,在给定情况下最简单的方法是用括号代替括号:

std::thread t{EchoServer(socket)};

注意,但是,这是保证调用<代码> STD::EndioTyter()/CODE >因为线程既不分离也不连接。

< P> C和C++编译器必须在解析时声明声明和范围的语义知识,并查阅这些知识,以便知道如何解析某些东西。 当一个标识符被扫描时,它可以被转换为一个标记,该标记的词法类别基于该标识符在扫描发生的范围内的声明方式

一个比你更简单的例子是:

A ( B );
这可能是函数调用:调用函数
a
时使用的参数是主表达式
B
的值。或者,它可能是名称
B
的声明,该声明将是
a
类型的对象


如果我们的词法分析器能够窥探当前作用域中可见的声明,它可以确定A是类型名还是声明为函数。然后,它可以将适当类型的标记传递给解析器,从而匹配适当的短语结构规则。

如您所述,有两个位置对该语句的解释是不可能的,但该标准明确规定,在这种不明确的情况下,编译器必须将该语句解释为函数定义(删除额外的括号集):

如果要强制创建
std::thread
,可以添加一组额外的括号,使语句不是有效的函数声明:

std::thread t((EchoServer(socket)));
使用不同的语法进行初始化:

std::thread t = std::thread(EchoServer(socket));
或者,由于您使用的是C++11,因此可以使用统一初始化:

std::thread t = std::thread(EchoServer(socket));

前两个选项是有效的C++03,但在C++11编译器中,您可能应该使用第三个选项(使用
std::thread
表示您正在使用C++11功能)

查找“最麻烦的解析”。
std::thread t((EchoServer(socket));
std::thread t{EchoServer(socket)};
?(更多C++11)我想这是因为没有可用的
std::thread
构造函数接受类型为
class EchoServer
的参数。这是我们在这个问题上的常见问题,尽管我对是否将其作为副本关闭有点矛盾。问题当然是。我无法调用t.detach()一般来说,我认为您实际上不想调用
detach()
无论如何,因为这只意味着你有一个流氓线程无法正确清理…但这是一个单独的问题;)socket不是同一类型的EchoServer,所以它不能compile@elvis:您试过了吗?它不需要是相同的类型,只需要是可转换的…这也是您试图编写的代码所必需的。第三个代码段不仅仅是一种不同的初始化语法,它是一种完全不同的初始化方式。@BenVoigt:这三个代码段的初始化方式都略有不同,在这种情况下,它们的作用是相同的。第一个代码段是直接初始化,只需要采用
EchoServer,第二种是副本初始化。§8.5/15实际上使第三种情况与第一种情况相同,并将其命名为直接初始化,尽管在§12.6.2/2中指出,该语法将具有类类型对象的列表初始化语义,尤其是直接列表初始化。[…]语义与直接初始化相同,除非类型具有初始值设定项列表构造函数(其第一个参数是
std::initializer\u list
的构造函数,并且没有其他没有默认值的参数).由于在
std::thread
中不是这种情况,因此在这种情况下,直接列表初始化相当于直接初始化(即将调用相同的构造函数).这个详细的描述是否适合回答是另一个问题。我原本认为这超出了范围,但现在是:)我更担心
std::thread t((EchoServer(socket)));
std::thread t = std::thread(EchoServer(socket));
std::thread t{EchoServer(socket)};