我编写了一个使用ZeroMQ的C ++ 11程序。
在一个特定的行中,我想创建一个新的消息作为局部变量,并使用"almost always auto"样式的语法用serialized
向量的大小初始化它:
auto zm = zmq::message_t {serialized.size()};
这在我的机器上编译好(让我们称它为机器“A”;使用Clang ++版本3.4.2-13并使用g ++版本4.9.1),而在同事的机器上(“B”;使用Clang ++版本3.5) .0-10)发生错误:
error: calling a private constructor of class 'zmq::message_t'
auto zm = zmq::message_t {serialized.size()};
^
/usr/include/zmq.hpp:192:9: note: declared private here
message_t (const message_t&);
^
两台机器都在运行Debian 8.0(jessie)。机器A已安装libzmq3-dev(ZeroMQ版本4.0.5 + dfsg-2),而在机器B上安装libzmq-dev(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上的错误消失了。
我的问题是:
我打算调用message_t (size_t)
构造函数。为什么尝试在机器B上使用私有的message_t (const message_t&)
?
使错误消失的代码更改将删除赋值运算符。那么为什么编译器不会抱怨void operator = (const message_t&)
是私有的,而是message_t (const message_t&)
?
为什么机器A上没有错误,虽然message_t (const message_t&)
也是私有的?我想这与message_t (size_t)
被声明为explicit
有关,但我不明白这个关键字的效果。 (编辑:我原本不知道机器A版本中有移动构造函数,机器B的版本中不存在。)
答案 0 :(得分:2)
继
auto zm = zmq::message_t {serialized.size()};
不是指派,
但是使用移动或复制构造函数(可能被省略)初始化zm
,这应该是可访问的(即使它被省略)。
临时构建符合预期explicit message_t (size_t)
。
我怀疑Clang ++版本3.4.2-13中有一个错误,因为你应该有与机器B相同的错误。(在A中移动运算符,B没有解释这种行为)。
答案 1 :(得分:1)
auto zm = zmq::message_t {serialized.size()};
是一个变量声明,因此在这种情况下, = 是一个复制初始化,而不是一种影响,这就是为什么这是被调用的构造函数而不是影响运算符。
显式关键字意味着构造函数仅被考虑用于直接初始化,这是
zmq::message_t zmq {serialized.size()};
您可以在此处找到更多详细信息和示例:http://en.cppreference.com/w/cpp/language/explicit
答案 2 :(得分:-1)
转动
auto zm = zmq::message_t {serialized.size()};
进入
izmq::message_t zm {serialized.size()};
作为=调用(不受欢迎的,私有的)复制构造函数