初始化std :: array而不复制/移动元素

Mar*_*s K 7 c++ initialization copy-constructor c++11 stdarray

#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()
{}
Run Code Online (Sandbox Code Playgroud)

这将无法编译(带有NDK和clang的Android Studio)带有"调用已删除的c构造函数"错误.我知道我可以使用a std::vectoremplace_back()直接在容器内构造一个元素,但在我的代码中我只想使用固定大小的容器和不可复制/可移动的对象进行优化.我可能在这里缺少基本的,但是没有一种方法来初始化,std::array而不必先构建单个元素然后将它们复制到那里?

jua*_*nza 7

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

std::array<c,2> array = {{{"",""},{"",""}}};
Run Code Online (Sandbox Code Playgroud)

要么

std::array<c,2> array{{{"",""},{"",""}}};
Run Code Online (Sandbox Code Playgroud)


son*_*yao 6

从C++ 17开始,从某些特定情况开始,可以保证复制省略.

在下列情况下,编译器需要省略类对象的复制和移动构造函数,即使复制/移动构造函数和析构函数具有可观察的副作用:

  • 在初始化中,如果初始化表达式是prvalue且源类型的cv-nonqualified版本与目标类相同,则初始化表达式用于初始化目标对象:

    T x = T(T(T())); // only one call to default constructor of T, to initialize x
    
    Run Code Online (Sandbox Code Playgroud)

对于这些情况,不需要访问复制/移动构造函数.

When copy-elision takes place (until C++17) In those cases where copy-elision is not guaranteed, if it takes place (since C++17) 并且不调用copy-/move-构造函数,它必须存在且可访问(好像根本没有发生优化),否则程序是不正确的.

生活