1

我正在尝试组合一个高效的 C++1x 结构,该结构可以利用高效的 std::move/copy 构造/和赋值操作。这些结构分为 2 个基本类别,POD 结构和非 POD 结构。我已经养成使用样板代码编写这些结构的习惯,但我很确定编译器在这方面可以做得比我做得更好,而且每个类都需要大量输入。我的问题是利用默认编译器操作我能做的最低限度是什么。例如,我知道,一旦我定义了一个显式构造函数,它就会抑制移动和赋值运算符的自动生成。此外,我希望没有超类的非 POD 结构具有默认析构函数,而那些从基类继承的结构具有默认的虚拟析构函数。

PAGE_DATA 结构的原始版本如下

using PAGE_DATA = struct page_data {
    std::string name;
    std::vector<SCRN_TEXT> elements;
    std::vector<int> jumpTable;
};

然后,我添加了样板代码以使该数据结构能够感知移动,并且我还添加了一个显式构造函数(没有它,我不得不使用读起来不太好的大括号通过聚合初始化来初始化它)。

using PAGE_DATA = struct page_data {
    explicit page_data(const std::string& rName = std::string(), 
        const std::vector<SCRN_TEXT>& rElements = std::vector<SCRN_TEXT>(), 
        const std::vector<int>& rJumpTable = std::vector<int>())
        : name(rName)
        , elements(rElements)
        , jumpTable(rJumpTable)
    {}
    //! Defaulted copy constructor.
    page_data(const page_data&) = default;
    //! Defaulted move constructor.
    page_data(page_data&&) = default;

    //! Non-throwing copy-and-swap idiom unified assignment.
    page_data& operator=(page_data rhs) {
        rhs.swap(*this);
        return *this;
    }

    //! Non-throwing-swap idiom.
    void swap(page_data& rhs) noexcept {
        // enable ADL (not necessary in our case, but good practice)
        using std::swap;
        // swap base members
        // ...
        // swap members here
        swap(name, rhs.name);
        swap(elements, rhs.elements);
        swap(jumpTable, rhs.jumpTable);
    }

    virtual ~page_data() = default;

    std::string name;
    std::vector<SCRN_TEXT> elements;
    std::vector<int> jumpTable;
}; 

调用的相关简单 POD 结构如下所示:

using COLOR_TYPE = enum color_type
{
    BLACK   = 0x0,
    CYAN    = 0x1,
    RED     = 0x2,
    YELLOW  = 0x3,
    GREEN   = 0x4,
    MAGENTA = 0x5,
    AMBER   = 0x6,
    WHITE   = 0x7
};

using SIZE_TYPE = enum size_type {
    SMALL_CHAR = 0x0,
    BIG_CHAR = 0x1
};

using MODIFY_TYPE = enum modify_type {
    NORMAL      = 0x0,
    UNDER       = 0x2,
    FLASH       = 0x4,
    FLASH_UNDER = 0x6
};

using SCREEN_ATTR = struct screen_attr {
    COLOR_TYPE    color  : 4;
    SIZE_TYPE     size   : 2;
    MODIFY_TYPE   blink  : 4;
    unsigned char unused : 6;
};

using CDU_ROWCOL = struct cdu_rowcol {
    int  v;
    int  h;
};

using SCRN_TEXT = struct scrn_text {
    CDU_ROWCOL loc;
    SCREEN_ATTR  attrib;
    std::string text;
};

在整理了一个现场大肠杆菌演示后,我能够验证样板做正确的事情。

int main() {
    std::cout << "assertions work fine" << std::endl;
    static_assert(std::is_copy_constructible<PAGE_DATA>(), "not copy constructible");
    static_assert(std::is_move_constructible<PAGE_DATA>(), "not move constructible");
}
4

3 回答 3

3

你原来的结构已经完全可以移动建造了。您编写的所有额外样板代码都已在需要时由编译器生成。

于 2016-12-08T16:05:04.843 回答
2

我的问题是利用默认编译器操作我能做的最低限度是什么。

最小值——这是相当理想的数量——是您的原始版本,它充分利用了默认操作。

page_data::swap的效率可能比泛型稍微高一点,std::swap并且它不会阻止任何隐式成员函数的生成,因此可能值得保留。但是,如果有的话,它可能只会稍微好一点,所以你可能想衡量它是否值得弄乱你的类定义。

于 2016-12-08T16:08:19.743 回答
0

我喜欢我的问题的这个答案,“......如果你发现自己在编写移动运算符和移动构造函数,那是因为你没有充分分解问题。”

于 2016-12-08T16:04:32.127 回答