std::ranges::uninitialized_default_construct
cppreference.net에서
| 헤더 <memory>
|
||
| 에 정의됨 |
||
template< /*nothrow-forward-iterator*/ I, /*nothrow-sentinel-for*/<I> S >
requires std::default_initializable<std::iter_value_t<I>>
I uninitialized_default_construct( I first, S last );
|
호출 시그니처 | (C++20 이후) (C++26부터 constexpr) |
template< /*nothrow-forward-range*/ R >
requires std::default_initializable<ranges::range_value_t<R>>
ranges::borrowed_iterator_t<R>
uninitialized_default_construct( R&& r );
|
(2) | (C++20 이후) (C++26부터 constexpr) |
template< /*execution-policy*/ Ep, /*nothrow-random-access-iterator*/ I,
/*nothrow-sized-sentinel-for*/<I> S >
requires std::default_initializable<std::iter_value_t<I>>
I uninitialized_default_construct( Ep&& policy, I first, S last );
|
(3) | (C++26 이후) |
template< /*execution-policy*/ Ep, /*nothrow-sized-random-access-range*/ R >
requires std::default_initializable<ranges::range_value_t<R>>
ranges::borrowed_iterator_t<R>
uninitialized_default_construct( Ep&& policy, R&& r );
|
(4) | (C++26 이후) |
의 정의는 /*execution-policy*/이 페이지를 참조하십시오; 다른 설명 전용 개념의 정의는 이 페이지를 참조하십시오.
1) 다음과 같이
[first, last)대상 범위 의 요소를
for (; first != last; ++first)
::new (기본 초기화(*first))
std::remove_reference_t<std::iter_reference_t<I>>;
return first;
로 생성합니다.
만약 초기화 중에 예외가 발생하면, 이미 생성된 객체들은 지정되지 않은 순서로 소멸됩니다.2)과 같지만,
r를 대상 범위로 사용합니다.3,4)과 같지만, 에 따라 실행됩니다.
policy이 페이지에 설명된 함수형 개체는 알고리즘 함수 개체입니다 (비공식적으로 니블로이드라고 함). 즉,
- 이들 중 하나를 호출할 때 명시적 템플릿 인자 목록을 지정할 수 없습니다.
- 그중 어느 것도 인자 종속 검색에 보이지 않습니다.
- 이들 중 하나가 일반 비한정 검색에 의해 함수 호출 연산자의 왼쪽 이름으로 발견되면, 인자 종속 검색이 억제됩니다.
매개변수
| first, last | - | 초기화할 요소들의 범위를 정의하는 반복자-센티넬 쌍 |
| r | - | 초기화할 요소들의 범위 |
| policy | - | 사용할 실행 정책 |
반환값
위에서 설명한 바와 같습니다.
예외
대상 범위에 있는 요소의 생성 중 발생하는 모든 예외.
3,4) 실행 과정 중:
- 병렬 처리에 필요한 임시 메모리 자원을 사용할 수 없는 경우 std::bad_alloc이 발생합니다.
- 알고리즘 인수를 통해 객체에 접근하는 동안 잡히지 않은 예외가 발생하면, 실행 정책에 따라 동작이 결정됩니다(표준 정책의 경우 std::terminate이 호출됩니다).
참고
구현은 std::iter_value_t<I> 객체를 기본 초기화하는 동안 중요하지 않은 기본 생성자가 호출되지 않으면 (관찰 가능한 효과를 변경하지 않고) 객체의 생성을 생략할 수 있으며, 이는 std::is_trivially_default_constructible로 감지할 수 있습니다.
| 기능 테스트 매크로 | 값 | 표준 | 기능 |
|---|---|---|---|
__cpp_lib_parallel_algorithm |
202506L |
(C++26) | 병렬 범위 알고리즘 |
__cpp_lib_raw_memory_algorithms |
202411L |
(C++26) | constexpr for 전문화된 <memory> 알고리즘, (1,2)
|
가능한 구현
struct uninitialized_default_construct_fn
{
template</*nothrow-forward-iterator*/ I, /*nothrow-sentinel-for*/<I> S>
requires std::default_initializable<std::iter_value_t<I>>
constexpr I operator()(I first, S last) const
{
using value_type = std::remove_reference_t<std::iter_reference_t<I>>;
if constexpr (std::is_trivially_default_constructible_v<value_type>)
return ranges::next(first, last); // skip initialization
I rollback{first};
try
{
for (; !(first == last); ++first)
::new (static_cast<void*>(std::addressof(*first))) value_type;
return first;
}
catch (...) // rollback: destroy constructed elements
{
for (; rollback != first; ++rollback)
ranges::destroy_at(std::addressof(*rollback));
throw;
}
}
template</*nothrow-forward-range*/ R>
requires std::default_initializable<ranges::range_value_t<R>>
constexpr ranges::borrowed_iterator_t<R> operator()(R&& r) const
{
return (*this)(ranges::begin(r),
ranges::next(ranges::begin(r), ranges::end(r)));
}
};
inline constexpr uninitialized_default_construct_fn uninitialized_default_construct{};
|
예제
이 코드 실행
#include <cstring> #include <iostream> #include <memory> #include <string> int main() { struct S { std::string m{"▄▀▄▀▄▀▄▀"}; }; constexpr int n{4}; alignas(alignof(S)) char out[n * sizeof(S)]; try { auto first{reinterpret_cast<S*>(out)}; auto last{first + n}; std::ranges::uninitialized_default_construct(first, last); auto count{1}; for (auto it{first}; it != last; ++it) std::cout << count++ << ' ' << it->m << '\n'; std::ranges::destroy(first, last); } catch (...) { std::cout << "Exception!\n"; } // "trivial types"의 경우 uninitialized_default_construct는 // 일반적으로 주어진 초기화되지 않은 메모리 영역을 0으로 채우지 않습니다. constexpr char sample[]{'A', 'B', 'C', 'D', '\n'}; char v[]{'A', 'B', 'C', 'D', '\n'}; std::ranges::uninitialized_default_construct(std::begin(v), std::end(v)); if (std::memcmp(v, sample, sizeof(v)) == 0) { std::cout << " "; // 정의되지 않은 동작일 수 있음, CWG 1997 해결 대기 중: // for (const char c : v) { std::cout << c << ' '; } for (const char c : sample) std::cout << c << ' '; } else std::cout << "Unspecified\n"; }
가능한 출력:
1 ▄▀▄▀▄▀▄▀ 2 ▄▀▄▀▄▀▄▀ 3 ▄▀▄▀▄▀▄▀ 4 ▄▀▄▀▄▀▄▀ A B C D
참고 항목
| 초기화되지 않은 메모리 영역에 시작점과 개수로 정의된 위치에 객체를 기본 초기화 방식으로 생성합니다 (알고리즘 함수 개체) | |
| 초기화되지 않은 메모리 영역에 범위로 정의된 위치에 객체를 값 초기화 방식으로 생성합니다 (알고리즘 함수 개체) | |
| 초기화되지 않은 메모리 영역에 시작점과 개수로 정의된 위치에 객체를 값 초기화 방식으로 생성합니다 (알고리즘 함수 개체) | |
| 초기화되지 않은 메모리 영역에 범위로 정의된 위치에 객체를 기본 초기화 방식으로 생성합니다 (함수 템플릿) |