我有以下类:
// NetworkManager.hpp
class NetworkManager : public QObject {
Q_OBJECT
public:
NetworkManager(QHostAddress const& address, quint16 port);
private:
QHostAddress const& _address;
quint16 const _port;
};
// NetworkManager.cpp
NetworkManager(QHostAddress const& address, quint16 const port)
: _address(address)
, _port(port)
{
}
此类包含在结构中:
struct Context {
NetworkManager networkManager
};
我这样初始化这个结构:
class A {
public:
A() : _context({{QHostAddress::SpecialAddress::LocalHost, 1337}})
{
}
private:
Context _context;
};
问题是当结构被初始化时,它调用NetworkManager复制构造函数,默认情况下会被删除,因为它继承了QObject。但是当我使用不同的初始化,_context{{QHostAddress::SpecialAddress::LocalHost, 1337}}
,一切正常。为什么会发生这种情况?
我使用Clang编译器和C++20标准。
2条答案
按热度按时间bprjcwpo1#
第一个代码示例是构造一个临时对象,然后将其传递给
_context
的复制构造函数。_context({{QHostAddress::SpecialAddress::LocalHost, 1337}})
基本上与第二个示例
_context{{QHostAddress::SpecialAddress::LocalHost, 1337}}
正在就地构造_context对象,没有创建临时对象,因此没有执行复制。jyztefdp2#
此问题是由两个初始化之间的初始化器列表语法差异引起的:
A():_context({{Q主机地址::特殊地址::本地主机,1337}})
以及
A():_context{{Q主机地址::特殊地址::本地主机,1337}}
在第一种情况下,外部大括号{}创建了一个新的内部初始化器列表,而在第二种情况下,它们是与外部初始化器列表相同的初始化器列表的一部分。这意味着在第一种情况下,NetworkManager构造函数是用单个参数调用的,这是一个初始化器列表,而在第二种情况下,它是用两个参数调用的,它们是QHostAddress和quint 16值。
由于NetworkManager构造函数有两个参数,第一次初始化将尝试调用复制构造函数,由于NetworkManager继承自QObject,复制构造函数在默认情况下被删除,这会导致编译错误。
另一方面,第二个初始化是正确的,因为它向NetworkManager构造函数传递了正确数量的参数。
要解决此问题,您可以使用第二种初始化语法,或者为NetworkManager定义一个自定义复制构造函数以允许复制它。