균일 한 중괄호 배열 초기화를위한 복사 제거 보장-C ++ 17 이후 필수 사항이 아니어야합니까? [복제]

Dec 06 2020

내가 새 규칙을 올바르게 이해하는 한

https://en.cppreference.com/w/cpp/language/copy_elision

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

이 코드는 C ++ 17 표준 준수 컴파일러 용으로 컴파일되어야합니다.

struct NonTrivialClass
{
    ~NonTrivialClass( ){  }
};

class MainNonTrivialClass 
{
public:
  MainNonTrivialClass(int t) : m_simpleTypeMember(t) { }
 
  virtual void makeMySelfNonTrivial() {}

  MainNonTrivialClass( const MainNonTrivialClass& other) = delete;
  MainNonTrivialClass& operator=( const MainNonTrivialClass& other) = delete;
  MainNonTrivialClass(MainNonTrivialClass&& other) = delete;
  MainNonTrivialClass& operator=(MainNonTrivialClass&& other) = delete;
  
  NonTrivialClass m_nontrivialMember;
  int m_simpleTypeMember;
};

class ArrayContainer
{
public:
  ArrayContainer() : m_array{{1}, {2} } {}

private:
  MainNonTrivialClass m_array[2];
};


int main()
{
  ArrayContainer accContainer;
}

그러나 gcc 9.1.0 with -std = c ++ 17 -O2 -Wall -pedantic은 말합니다 (C ++ 17 이전의 경우 완전히 예상 됨)

main.cpp: In constructor 'ArrayContainer::ArrayContainer()':
main.cpp:25:39: error: use of deleted function 'MainNonTrivialClass::MainNonTrivialClass(MainNonTrivialClass&&)'
   25 |   ArrayContainer() : m_array{{1}, {2} } {}
      |                                       ^
main.cpp:15:3: note: declared here
   15 |   MainNonTrivialClass(MainNonTrivialClass&& other) = delete;

이런 식으로 배열 균일 초기화는 요소 별 복사 초기화 (?)로 정의되며 복사 제거로 이어져야하므로 실제로 무슨 일이 일어나는지 이해하지 못합니다. 이전 C ++ 17 이전 규칙이 여기에 적용되는 것 같습니다. 더 궁금한 점은 MainNonTrivialClass에서 m_nontrivialMember를 제거하면 동일한 코드가 잘 컴파일되지만 복사 제거가 아닌 경우 항상 해당 복사 / 이동 생성자의 존재를 강제하기 때문에 동일한 컴파일 오류가 발생하지 않아야한다는 것입니다. ?

답변

1 ecatmur Dec 06 2020 at 18:22

이 구문은 직접 초기화 인 C ++ 17 이전 버전에서도 작동합니다. GCC 버그 63707 을 참조하는 삭제 된 복사 생성자 (C ++ 11) 를 사용 하여 클래스 배열을 초기화하는 방법을 참조하세요 .