在没有 copying/moving 元素的情况下初始化 std::array

initialize std::array without copying/moving elements

#include <iostream>
#include <string>
#include <array>

class C {
private:
    std::string a;
    std::string b;
    std::string c;
public:
    C(std::string a_, std::string b_, std::string c_) : a{a_},b{b_},c{c_} {}
    ~C(){};
    C(const C&) =delete;
    C(const C&&) =delete;
    const C& operator=(const C&) =delete;
    const C& operator=(const C&&) =delete;
};

std::array<C,2> array = {C("","",""),C("","","")};

int main()
{}

这将无法编译(Android Studio with NDK and clang)并出现 "call to deleted constructor of c" 错误。我知道我可以使用 std::vectoremplace_back() 直接在容器内构造元素,但在我的代码中我只想使用固定大小的容器和 non-copyable/moveable 对象进行优化。我可能在这里遗漏了一些基本的东西,但是没有一种方法可以初始化 std::array 而不必首先构造各个元素然后将它们复制到那里吗?

您可以使用大括号括起来的初始值设定项而不是临时 c 对象:

std::array<c,2> array = {{{"",""},{"",""}}};

std::array<c,2> array{{{"",""},{"",""}}};

从 C++17 开始,对于某些特定情况 copy elision 是有保证的。

Under the following circumstances, the compilers are required to omit the copy- and move- constructors of class objects even if copy/move constructor and the destructor have observable side-effects:

  • In initialization, if the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object:

    T x = T(T(T())); // only one call to default constructor of T, to initialize x
    

对于这些情况,copy/move 构造函数不需要可访问。

When copy-elision takes place (until C++17) In those cases where copy-elision is not guaranteed, if it takes place (since C++17) and the copy-/move-constructor is not called, it must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed.

LIVE