원자 벡터의 초기화


12

치다:

void foo() {
  std::vector<std::atomic<int>> foo(10);
  ...
}

foo의 내용이 이제 유효합니까? 아니면 명시 적으로 반복하고 초기화해야합니까? 나는 Godbolt를 확인했는데 괜찮아 보이지만이 시점에서 표준이 매우 혼란스러워 보입니다.

표준 : : 벡터 생성자는 삽입 말한다 기본 삽입 의 인스턴스 std::atomic<int>이며, 초기화 값 배치를 통해를 new.

가치 초기화의이 효과가 적용된다고 생각합니다.

2) T가 사용자 제공 또는 삭제되지 않은 기본 생성자를 가진 클래스 유형 인 경우 (즉, 암시 적으로 정의되거나 기본 기본 생성자를 가진 클래스 일 수 있음), 객체는 0으로 초기화 된 다음 사소한 기본 생성자가 있으면 기본값으로 초기화됩니다.

그래서 원자는 0으로 초기화 된 것 같습니다. 문제는, std::atomic<int>결과를 0으로 초기화 하면 유효한 객체가됩니까?

나는 대답이 "실제로 그렇지만 실제로 정의되어 있지는 않다"고 추측 할 것입니다.

참고 : 이 답변 은 0으로 초기화되었음을 동의하지만 객체가 유효하다는 것을 실제로 말하지는 않습니다.

답변:


7

당신은 걱정하는 것이 맞습니다. 표준에 따르면 원자는 기본 생성자라고하지만 초기화 되지 않았습니다. 기본 생성자가 원자를 초기화하지 않기 때문입니다.

기본값으로 초기화 std::atomic<T>T개체 에는 개체 가 포함되어 있지 않으며 std :: atomic_init에 의한 유일한 사용은 소멸 및 초기화입니다.

이것은 다소 일반적인 언어 규칙을 위반하는 것이며, 일부 구현은 어쨌든 초기화합니다 (알다시피).

즉, 표준에 따라 올바르게 초기화되었는지 100 % 확인하기 위해 추가 단계를 수행하는 것이 좋습니다. 결국 버그를 추적하기가 매우 어려운 동시성을 처리합니다.

래퍼 사용을 비롯하여 여러 가지 방법으로 문제를 피할 수 있습니다.

struct int_atomic {
   std::atomic<int> atomic_{0};//use 'initializing' constructor
};

또는 실제로 사용하십시오 atomic_init. 어쨌든 질문의 코드 주위를 이미 동기화해야합니다.
Lightbit Races in Orbit

기본 생성자는 사소한 것이기 때문에 어쨌든 불려 지지 않습니다 (질문에 인용)
Orbit의 Lightness Races

@LightnessRaceswithMonica 또한 가능합니다. 래퍼를 강조하고
싶습니다

@LightnessRaceswithMonica는 일부 컴파일러가이 예외를 구현하지 않더라도 일반 언어 규칙에 대한 예외입니다. StoreTeller의 답변이 100 % 정확하다는 것을 확신하지 못합니다.
darune

2

기본 생성자가 호출 된 경우에도 (사소하지 않기 때문에) 실제로 아무것도하지 않습니다 .

제로 초기화는 분명히 유효한 원자를 생성한다고 보장 할 수 없습니다. 우연히 모든 멤버를 0으로 초기화하여 유효한 원자가 생성 된 경우에만 작동합니다 .

또한 원자는 복사 할 수 없으므로 벡터 생성자에 초기화 값을 제공 할 수 없습니다.

이제 컨테이너와 std::atomic_init각 요소를 반복해야합니다 . 이 문제를 해결해야하는 경우, 같은 이유로 이미 벡터 생성을 동기화하고 있기 때문에 좋습니다.


@darune 나는 일종의 동기화를 고려한다;)
Orbit in
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.