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


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.