C++11 高效地创建C++;11移动和复制感知结构

C++11 高效地创建C++;11移动和复制感知结构,c++11,struct,c++14,move,defaulted-functions,C++11,Struct,C++14,Move,Defaulted Functions,我正在尝试组合一个高效的C++1x结构,它可以利用高效的std::move/copy构造/和赋值操作。这些结构分为两个基本类别,POD结构和非POD结构。我已经养成了使用样板代码编写这些结构的习惯,但我非常确信编译器在这方面可以做得比我更好,而且每个类都需要相当多的键入。我的问题是,为了利用默认的编译器操作,我能做的最低限度是什么。例如,我知道一旦定义了一个显式构造函数,就会禁止自动生成move和assignment操作符。此外,我希望没有超类的非POD结构具有默认析构函数,而从基类继承的非PO

我正在尝试组合一个高效的C++1x结构,它可以利用高效的std::move/copy构造/和赋值操作。这些结构分为两个基本类别,POD结构和非POD结构。我已经养成了使用样板代码编写这些结构的习惯,但我非常确信编译器在这方面可以做得比我更好,而且每个类都需要相当多的键入。我的问题是,为了利用默认的编译器操作,我能做的最低限度是什么。例如,我知道一旦定义了一个显式构造函数,就会禁止自动生成move和assignment操作符。此外,我希望没有超类的非POD结构具有默认析构函数,而从基类继承的非POD结构具有默认虚拟析构函数。关于如何有效地执行这些操作的规则对我来说总是有点混乱

页面数据结构的原始版本如下

using PAGE_DATA = struct page_data {
    std::string name;
    std::vector<SCRN_TEXT> elements;
    std::vector<int> jumpTable;
};
在完成一个测试后,我能够验证锅炉板是否正确

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");
}
intmain(){

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

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

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

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

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

最小值——这是最佳值——是您的原始版本,它充分利用了默认操作

您的
page\u data::swap
可能比泛型
std::swap
稍有效,并且它不会阻止任何隐式成员函数的生成,因此可能值得保留。但是,如果有可能,它可能只会稍微好一些,因此您可能需要衡量是否值得将类定义弄得乱七八糟n

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

最小值——这是最佳值——是您的原始版本,它充分利用了默认操作


您的
page\u data::swap
可能比泛型
std::swap
稍有效,并且它不会阻止任何隐式成员函数的生成,因此可能值得保留。但是,如果有可能,它可能只会稍微好一些,因此您可能需要衡量是否值得将类定义弄得乱七八糟n、

为什么你坚持在每个结构声明前面粘贴
使用所有大写=
?这不是C,你可以
typedef struct
东西。@Nicolas,这是C++11的别名(现代的typedef)表示法。大写是别名,小写是结构,这允许我同时使用Typedef和struct,小写的一个用于定义构造函数签名。我知道
使用
意味着什么。我不知道为什么你认为这样做很重要,甚至是个好主意。就像我说的,这不是C。在C中,
strUCT单独创建一个类型名称;在C++中,它是.<代码> StutsAuto是一个完全有效的类型名称。您不需要TyBuff/使用<代码> StutsAuto。为什么在所有结构声明前面都坚持使用AlxBase= ?是C++11的别名(现代类型定义)表示法。大写是别名,小写是结构,这允许我同时使用Typedef和struct,小写的一个用于定义构造函数签名。我知道
使用
意味着什么。我不知道为什么你认为这样做很重要,甚至是个好主意。就像我说的,这不是C。在C中,
strUCT< <代码>不能创建一个类型名;在C++中,它是.<代码> StutsAuto是一个完全有效的类型名称。您不需要TyBuff/使用<代码> StutsAuto。问题是我需要添加一个显式的默认构造函数来避免括号初始化。k({..},{..},{..})这些或使用聚合初始值设定项创建本地PAGE_数据结构。如果我继承了非POD简单结构会发生什么情况。我不确定在可能有struct Foo:public Bar的情况下会发生什么,以及如何确保Foo使用Bar等做了所有正确的事情,@johnco3:“问题是我需要添加一个显式的默认构造函数来避免大括号初始化。"…为什么要?您公开了所有成员;为什么要阻止人们对其使用聚合初始化?仅添加默认构造函数如何比实现复制/移动操作更糟糕?问题是,我需要添加显式默认构造函数以避免大括号初始化。我有t的向量这些页面是数据结构。我必须将页面放回({..},{..},{..},{..})或者使用聚合初始值设定项创建本地PAGE_数据结构。如果我使用非POD简单结构进行继承会发生什么情况。我不确定在可能使用struct Foo:public Bar的情况下会发生什么,以及如何确保Foo使用Bar等做了所有正确的事情,@johnco3:“问题是,我需要添加一个显式的默认构造函数来避免大括号初始化。”…为什么要这样做?你让所有成员都公开了
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");
}