以“几乎总是自动”样式初始化ZeroMQ 2.2消息想要使用私有构造函数

时间:2015-05-27 11:21:27

标签: c++ c++11 constructor initialization zeromq

我编写了一个使用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上的错误消失了。

我的问题是:

  1. 我打算调用message_t (size_t)构造函数。为什么尝试在机器B上使用私有的message_t (const message_t&)

  2. 使错误消失的代码更改将删除赋值运算符。那么为什么编译器不会抱怨void operator = (const message_t&)是私有的,而是message_t (const message_t&)

  3. 为什么机器A上没有错误,虽然message_t (const message_t&)也是私有的?我想这与message_t (size_t)被声明为explicit有关,但我不明白这个关键字的效果。 (编辑:我原本不知道机器A版本中有移动构造函数,机器B的版本中不存在。)

3 个答案:

答案 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()};

作为=调用(不受欢迎的,私有的)复制构造函数