2017-02-09 25 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() 
{} 

to nie skompiluje (Android Studio z NDK i clang) z błędem "call to deleted constructor of c". Wiem, że mogę np. użyj std::vector i emplace_back(), aby skonstruować element bezpośrednio w kontenerze, ale w moim kodzie chcę użyć tylko kontenerów o stałej wielkości i obiektów niekopiowalnych/ruchomych do optymalizacji. Prawdopodobnie brakuje mi tutaj czegoś podstawowego, ale czy nie istnieje sposób na zainicjowanie modelu std::array bez uprzedniego skonstruowania poszczególnych elementów, a następnie skopiowania ich tam?initialize std :: array bez kopiowania/przenoszenia elementów

+2

Nawiasem mówiąc nie trzeba umieścić te podkreślenia w swoich nazwach parametrów. 'C (std :: string a, std :: string b, std :: string c): a {a}, b {b}, c {c} {}' nie ma problemów z niejednoznacznością i robi to, czego się spodziewasz. – nwp

Odpowiedz

6

Można użyć usztywnień zamknięty inicjatorów zamiast tymczasowych c obiektów:

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

lub

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

Czy to przenośne rozwiązanie? Chodzi mi o to, że zależy to od implementacji tablicy std ::, musi zawierać dokładnie jeden element typu 'T [N]'. – marcinj

+0

@marcinj Jestem prawie tego pewien. Ostatnim razem sprawdziłem, czy wymóg nie jest taki, że 'std :: array' zawiera dokładnie jeden element typu' T [N] ', ale zachowuje się tak, jakby to zrobił. Pojawił się cały problem dotyczący tego, czy środkowe '{}' można pominąć, tj. Czy powinno to być również poprawne: '{{", ""}, {"", ""}} '. Ta ostatnia rzecz mogła się zmienić od czasu C++ 11. – juanchopanza

+0

Pytam, ponieważ czytałem jedno SO, w którym T.C. powiedział, że nie ma gwarancji: http://stackoverflow.com/questions/27669200/how-should-i-brace-initialize-an-stdarray-of-stdpairs#comment43754338_27669457. – marcinj

5

Wydaje się możliwe, ponieważ C++ 17, z tego dla niektórych określonych przypadkach copy elision jest gwarantowane .

W następujących okolicznościach kompilatory muszą pominąć przed kopiowaniem i move- konstruktorów klasy obiektów, nawet jeśli kopia/przenoszenie konstruktor i destruktor ma dostrzegalnych skutków ubocznych:

  • Podczas inicjowania, jeśli wyrażenie inicjalizacyjne jest wartością prival, a wersja niekodowana typu źródłowego jest tą samą klasą, co klasa miejsca docelowego, wyrażenie inicjujące jest używane do zainicjowania obiektu docelowego: :

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

A dla tych przypadkach, konstruktor kopia/ruch nie jest wymagane, aby były dostępne.

When copy-elision takes place (until C++17)In those cases where copy-elision is not guaranteed, if it takes place (since C++17) i przed kopiowaniem/move-konstruktor nie nazywa, to musi być obecny i dostępne (tak, jakby w ogóle się optimization), w przeciwnym razie program jest źle sformułowane.

LIVE

Powiązane problemy