생성자 이니셜 라이저에서 멤버 배열 초기화


98
class C 
{
public:
 C() : arr({1,2,3}) //doesn't compile
{}
    /*
    C() : arr{1,2,3} //doesn't compile either
{}
    */
private:
 int arr[3];
};

그 이유는 배열이 =구문으로 만 초기화 될 수 있다는 것입니다.

int arr[3] = {1,3,4};

질문

  1. 내가 원하는 일을 어떻게 할 수 있습니까 (즉, 생성자에서 배열을 초기화 합니다 (본문에 요소를 할당하지 않음)). 가능할까요?
  2. C ++ 03 표준은 ctor 이니셜 라이저에서 집합체 (배열 포함)를 초기화하는 것에 대해 특별한 언급이 있습니까? 아니면 위 코드의 무효는 다른 규칙의 결과입니까?
  3. C ++ 0x 이니셜 라이저 목록이 문제를 해결합니까?

추신 : 벡터, boost :: arrays 및 내가 잘 알고있는 배열에 대한 우월성은 언급하지 마십시오.


생성자를 제공하는 부스트 고정 크기 배열의 존재도 알고 있습니까?
— Benoît

2
@ Benoît : 맞아요. 하지만 일반 배열에 대해 알아야합니다. :)
— Armen Tsirunyan

답변:


55
  1. 내가 원하는 일을 어떻게 할 수 있습니까 (즉, 생성자에서 배열을 초기화합니다 (본문에 요소를 할당하지 않음)). 가능할까요?

예. 배열을 포함하는 구조체를 사용하고 있습니다. 당신은 이미 그것에 대해 알고 있다고 말했지만 나는 질문을 이해하지 못합니다. 그런 식으로, 당신은 할 몸에 할당하지 않고, 생성자의 배열을 초기화합니다. 이것이하는 일 boost::array입니다.

C ++ 03 표준은 ctor 이니셜 라이저에서 집합체 (배열 포함)를 초기화하는 것에 대해 특별한 언급이 있습니까? 아니면 위 코드의 무효가 다른 규칙의 결과입니까?

mem-initializer는 직접 초기화를 사용합니다. 그리고 8 항의 규칙은 이런 종류의 것을 금지합니다. 다음 경우에 대해 정확히는 모르겠지만 일부 컴파일러에서는 허용합니다.

struct A {
  char foo[6];
  A():foo("hello") { } /* valid? */
};

자세한 내용은 이 GCC PR 을 참조 하십시오.

C ++ 0x 이니셜 라이저 목록이 문제를 해결합니까?

예, 그렇습니다. 그러나 귀하의 구문이 유효하지 않은 것 같습니다. 목록 초기화를 시작하려면 중괄호를 직접 사용해야합니다.

struct A {
  int foo[3];
  A():foo{1, 2, 3} { }
  A():foo({1, 2, 3}) { } /* invalid */
};

내가 쓸 때 나는 이것을 우연히 발견했습니다 : char * const foo[6];반원. 그것은 필요 (11) C ++로 컴파일하려면 초기화를.
— JATothrim

33

C ++ 98은 배열을 0으로 만드는 것 (또는 POD가 아닌 요소의 경우 값 초기화) 외에는 직접 구문을 제공하지 않습니다. 그것을 위해 당신은 C(): arr() {}.

나는 Roger Pate가 C ++ 0x 집계 초기화의 제한 사항에 대해 틀렸다고 생각하지만, 조회하거나 확인하기에는 너무 게으르고, 중요하지 않습니다. 편집 : Roger가 "C ++ 03"에 대해 이야기하고 있었는데 "C ++ 0x"로 잘못 읽었습니다. 미안 해요, 로저. ☺

현재 코드에 대한 C ++ 98 해결 방법은 배열을 a에 래핑하고 struct해당 유형의 정적 상수에서 초기화하는 것입니다. 데이터는 어딘가에 있어야합니다. 커프에서 다음과 같이 보일 수 있습니다.

class C 
{
public:
    C() : arr( arrData ) {}

private:
     struct Arr{ int elem[3]; };
     Arr arr;
     static Arr const arrData;
};

C::Arr const C::arrData = {{1, 2, 3}};

0x에 어떤 한계가 있다고 말했습니까?

@Roger : "agrregate 초기화 ... ctor 이니셜 라이저에 맞지 않습니다". §12.5.2 / 1 의 mem-initializer 구문 인 C ++ 0x draft N3126을 확인하는 것만 으로 braced-init-list 사용이 포함 됩니다 .
— 건배와 hth. -Alf

6
내 문장의 처음 두 단어가 있습니다 에서 C ++ 03, ...

8

해결 방법 :

template<class T, size_t N>
struct simple_array { // like std::array in C++0x
   T arr[N];
};


class C : private simple_array<int, 3> 
{
      static simple_array<int, 3> myarr() {
           simple_array<int, 3> arr = {1,2,3};
           return arr;
      }
public:
      C() : simple_array<int, 3>(myarr()) {}
};

3
  1. 아니, 안타깝게도.
  2. 문법에 의해 허용되지 않기 때문에 원하는 방식으로 할 수 없습니다 (아래 참조). ctor와 유사한 초기화 만 사용할 수 있으며, 아시다시피 배열의 각 항목을 초기화하는 데 사용할 수 없습니다.
  3. 나는 그들이 여러 유용한 방법으로 전반적으로 초기화를 일반화하기 때문에 그렇게 생각합니다. 그러나 세부 사항은 확실하지 않습니다.

C ++ 03에서 집계 초기화는 아래와 비슷한 구문으로 만 적용되며, 이는 별도의 문이어야하며 ctor 이니셜 라이저에 맞지 않습니다.

T var = {...};

2

어때

...
  C() : arr{ {1,2,3} }
{}
...

?

g ++ 4.8에서 잘 컴파일됩니다.


이 표준입니까? 관련 조항을 인용 해 주시겠습니까?
— Armen Tsirunyan 2014 년

2
Visual C ++에서 컴파일하지 않습니다.
— sergiol

-2

생성자에서 int 배열을 초기화하고 싶습니까? 정적 배열을 가리 킵니다.

class C 
{
public:
    int *cArray;

};

C::C {
    static int c_init[]{1,2,3};
    cArray = c_init;
}

2
이 배열을 변경하면 해당 클래스의 모든 인스턴스에 대해 변경되기 때문에 이것은 나쁜 생각입니다.
— morty
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.