2017-02-09 92 views
5
#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与NDK和铿锵)与“调用删除C构造函数”错误。我知道我可以使用std::vectoremplace_back()直接在容器内构建元素,但在我的代码中,我只想使用固定大小的容器和不可复制/可移动的对象进行优化。我可能在这里缺少基本的东西,但是没有办法初始化std::array而无需先构建单个元素然后将它们复制到那里?初始化std :: array没有复制/移动元素

+2

通过你不需要把这些下划线在参数名的方式。 'C(std :: string a,std :: string b,std :: string c):a {a},b {b},c {c} {}'没有歧义问题,并且符合您的期望。 – nwp

回答

6

你可以用括号括初始化,而不是临时c对象:

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

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

它是一种便携式解决方案吗?我的意思是取决于std :: array是如何实现的,它必须包含一个'T [N]'类型的元素。 – marcinj

+0

@marcinj我很确定。上次我检查了这个要求并不是'std :: array'只包含'T [N]'类型的一个元素,但它的行为就像它一样。关于中间'{}'是否可以省略是一个完整的问题,也就是说这是否也应该是有效的:'{{“”,“”},{“”,“”}}'。自C++ 11以来,最后一件事可能已经发生了变化。 – juanchopanza

+0

我在问,因为我正在阅读一篇SO,T.C.说它不保证:http://stackoverflow.com/questions/27669200/how-should-i-brace-initialize-an-stdarray-of-stdpairs#comment43754338_27669457。 – marcinj

5

因为C++ 17它将成为可能,对于某些特定情况下copy elision保证。

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

  • 在初始化过程中,如果初始化表达式是一个prvalue,并且源类型的cv不合格版本与目标类的 类相同,则初始化表达式用于初始化目标对象 :

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

而对于这些情况,复制/移动构造不需要访问。

When copy-elision takes place (until C++17)In those cases where copy-elision is not guaranteed, if it takes place (since C++17)和 的禁止复制/移动构造函数不叫,它必须存在和 访问(因为如果没有优化发生在所有),否则病形成的 程序。

LIVE