C++ 正在初始化“中的ZeroMQ 2.2消息”;几乎总是自动的”;style希望使用私有构造函数
我已经编写了一个使用ZeroMQ的C++11程序 在某一行中,我想创建一条新消息作为局部变量,并使用-style语法将其初始化为名为C++ 正在初始化“中的ZeroMQ 2.2消息”;几乎总是自动的”;style希望使用私有构造函数,c++,c++11,constructor,initialization,zeromq,C++,C++11,Constructor,Initialization,Zeromq,我已经编写了一个使用ZeroMQ的C++11程序 在某一行中,我想创建一条新消息作为局部变量,并使用-style语法将其初始化为名为serialized的向量大小: auto zm = zmq::message_t {serialized.size()}; 在我的机器上(我们称之为机器“A”;使用Clang++3.4.2-13版,也使用g++4.9.1版),这可以很好地编译,而在同事的机器上(“B”;使用Clang++3.5.0-10版),则会发生错误: 错误:调用类“zmq::message
serialized
的向量大小:
auto zm = zmq::message_t {serialized.size()};
在我的机器上(我们称之为机器“A”;使用Clang++3.4.2-13版,也使用g++4.9.1版),这可以很好地编译,而在同事的机器上(“B”;使用Clang++3.5.0-10版),则会发生错误:
错误:调用类“zmq::message\t”的私有构造函数
auto zm=zmq::message_t{serialized.size()};
^
/usr/include/zmq.hpp:192:9:注意:此处声明为私有
消息(const message&);
^
两台机器都运行Debian8.0(jessie)。计算机A已安装(ZeroMQ版本4.0.5+dfsg-2),而计算机B上已安装(ZeroMQ版本2.2.0+dfsg-6)。在比较各自软件包中包含的zmq.hpp
的两个版本时,以下部分可能与此问题相关
在机器A上:
class message_t
{
// ...
public:
inline explicit message_t (size_t size_)
{
int rc = zmq_msg_init_size (&msg, size_);
if (rc != 0)
throw error_t ();
}
// ...
#ifdef ZMQ_HAS_RVALUE_REFS
inline message_t (message_t &&rhs) : msg (rhs.msg)
{
int rc = zmq_msg_init (&rhs.msg);
if (rc != 0)
throw error_t ();
}
inline message_t &operator = (message_t &&rhs)
{
std::swap (msg, rhs.msg);
return *this;
}
#endif
// ...
private:
zmq_msg_t msg;
message_t (const message_t&);
void operator = (const message_t&);
};
在机器B上:
class message_t : private zmq_msg_t
{
// ...
public:
inline message_t (size_t size_)
{
int rc = zmq_msg_init_size (this, size_);
if (rc != 0)
throw error_t ();
}
// no move constructor/move assignment
// ...
private:
message_t (const message_t&);
void operator = (const message_t&);
};
当我将代码更改为此
zmq::message_t zmq {serialized.size()};
机器B上的错误消失了
我的问题是:
消息(size\t)
构造函数。为什么有人试图在机器B上使用私有的message\u t(const message\u t&)
void操作符=(const message_t&)
是私有的,而是message_t(const message_t&)
message\u t(const message\u t&)
在那里也是私有的?我想这与message\u t(size\u t)
被声明为explicit
有关,但我不理解这个关键字的效果。(编辑:我最初不知道机器a的版本中有一个移动构造函数,而机器B的版本中不存在该构造函数。)
auto zm = zmq::message_t {serialized.size()};
不是转让,
但是使用move或copy构造函数(可以省略)初始化zm
,该构造函数应该是可访问的(即使省略)
按照预期使用显式消息(size\t)
构建临时消息
我怀疑Clang++版本3.4.2-13中有一个bug,因为您应该与机器B中有相同的错误。(B没有解释此行为的a中的移动操作符)
是一个变量声明,因此在本例中,=是一个副本初始化,而不是做作,这就是为什么这是被调用的构造函数,而不是做作运算符。Explicit关键字意味着构造函数只考虑直接初始化,这与
zmq::message_t zmq {serialized.size()};
您可以在这里找到更多详细信息和示例:但是为什么第一个语法不会导致机器A出现错误?我认为这不是Clang中的错误,因为它也使用g++版本4.9.1进行编译。(我更新了问题以提及这一点)。@mkrieger1:见。两个(最近的)clang/g++都(正确地)拒绝了代码。所以,如果示例代码适合您,那么就有一个bug。(或者将相关代码隐藏为move构造函数)。这是一个很好的观点。在机器a的ZeroMQ版本中确实有一个移动构造函数和一个移动分配,而在机器B的版本中没有。我已经更新了这个问题。
explicit
是否真的在这里起作用?explicit
在这里不起作用explicit
不允许调用void foo(message_t)
使用foo(42)
,您必须使用foo(message_t{42})
来调用它。是的,我已经知道了。我的问题是为什么会这样,为什么它不是其中一台机器上的错误。
auto zm = zmq::message_t {serialized.size()};
auto zm = zmq::message_t {serialized.size()};
zmq::message_t zmq {serialized.size()};