C++에서 배열의 모든 요소를 하나의 기본값으로 초기화하시겠습니까?
C++ 참고: 배열 초기화에는 배열 초기화보다 좋은 목록이 있습니다.나는 있습니다
int array[100] = {-1};
값이 -1로 가득 차 있을 것으로 예상되지만, 첫 번째 값만 가득 차 있고 나머지 값은 0과 랜덤 값이 혼합되어 있습니다.
코드
int array[100] = {0};
각 요소를 0으로 설정하여 정상적으로 작동합니다.
여기서 내가 놓치고 있는 것은..값이 0이 아니면 초기화할 수 없습니까?
그리고 2: 기본 초기화(위와 같이)가 전체 어레이를 통과하는 일반적인 루프보다 빠르며 값을 할당합니까? 아니면 동일한 작업을 수행합니까?
당신이 사용한 구문을 사용하면,
int array[100] = {-1};
says 는 첫 번째 를 " 첫번째요소다설로정다니합으"로 설정합니다.-1
그리고 나머지는0
생략된 모든 요소가 다음으로 설정되어 있기 때문에0
.
C++에서 모든 것을 다음으로 설정합니다.-1
당신은 (에서)와 같은 것을 사용할 수 있습니다.<algorithm>
):
std::fill_n(array, 100, -1);
휴대용 C에서, 당신은 당신 자신의 루프를 굴려야 합니다.컴파일러 확장이 있거나 구현 정의 동작을 바로 가기로 사용할 수 있습니다.
gcc 컴파일러에는 다음과 같은 구문을 허용하는 확장자가 있습니다.
int array[100] = { [0 ... 99] = -1 };
이렇게 하면 모든 요소가 -1로 설정됩니다.
이를 "지정된 초기화자"라고 합니다. 자세한 내용은 여기를 참조하십시오.
이것은 gcc c++ 컴파일러에서는 구현되지 않습니다.
연결한 페이지는 이미 첫 번째 부분에 대한 답을 제공했습니다.
명시적 배열 크기가 지정되었지만 더 짧은 초기화 목록이 지정된 경우 지정되지 않은 요소는 0으로 설정됩니다.
전체 배열을 0이 아닌 값으로 초기화하는 기본 제공 방법은 없습니다.
어떤 것이 더 빠른지에 대해서는 일반적인 규칙이 적용됩니다: "컴파일러에게 가장 많은 자유를 주는 방법은 아마도 더 빠를 것입니다."
int array[100] = {0};
컴파일러가 자유롭게 최적화할 수 있는 "이 100 ints를 0으로 설정"하는 것을 컴파일러에게 알려줍니다.
for (int i = 0; i < 100; ++i){
array[i] = 0;
}
훨씬 더 구체적입니다.컴파일러에게 반복 변수를 생성하도록 지시합니다.i
요소를 초기화해야 하는 순서 등을 알려줍니다.물론 컴파일러는 이 방법을 최적화할 가능성이 높지만 요점은 여기서 문제를 지나치게 지정하여 컴파일러가 동일한 결과를 얻기 위해 더 열심히 작업하도록 강요한다는 것입니다.
값으로 하려면 (에서는) 마막이로 0닌아값설면 (C++에서는) 지사를을 std::fill
:
std::fill(array, array+100, 42); // sets every value in the array to 42
다시 말하지만 배열에서도 동일한 작업을 수행할 수 있지만, 이 작업은 더 간결하고 컴파일러에게 더 많은 자유를 제공합니다.당신은 단지 전체 배열이 42 값으로 채워지기를 원한다고 말하는 것입니다.당신은 그것이 어떤 순서로 이루어져야 하는지 또는 다른 어떤 것에 대해서도 말하지 않습니다.
C++11에는 다음과 같은 다른 (불완전한) 옵션이 있습니다.
std::array<int, 100> a;
a.fill(-1);
용사를 합니다.std::array
우리는 이것을 C++14에서 꽤 간단한 방법으로 할 수 있습니다.C++11에서만 가능하지만 조금 더 복잡합니다.
우리의 인터페이스는 컴파일 시간 크기이며 기본값입니다.
template<typename T>
constexpr auto make_array_n(std::integral_constant<std::size_t, 0>, T &&) {
return std::array<std::decay_t<T>, 0>{};
}
template<std::size_t size, typename T>
constexpr auto make_array_n(std::integral_constant<std::size_t, size>, T && value) {
return detail::make_array_n_impl<size>(std::forward<T>(value), std::make_index_sequence<size - 1>{});
}
template<std::size_t size, typename T>
constexpr auto make_array_n(T && value) {
return make_array_n(std::integral_constant<std::size_t, size>{}, std::forward<T>(value));
}
를 위한 가 직접 .std::integral_constant<std::size_t, size>
그들 스스로, 그것은 꽤 말이 많은 구조이기 때문입니다.실제 작업은 처음 두 가지 기능 중 하나에 의해 수행됩니다.
간단합니다: " 번째과는매간니다단합우첫하부다니▁the합간단첫▁is".은 를구니다합을 건설합니다.std::array
0 사이즈의복사할 필요는 없습니다. 우리는 그것을 구성할 뿐입니다.
두 번째 과부하는 조금 더 까다롭습니다.하고, 소로얻 값은따전며달되라구, 또인스를성다니합의 를 구성합니다.make_index_sequence
그리고 다른 구현 함수를 호출합니다.그 기능은 어떻게 생겼습니까?
namespace detail {
template<std::size_t size, typename T, std::size_t... indexes>
constexpr auto make_array_n_impl(T && value, std::index_sequence<indexes...>) {
// Use the comma operator to expand the variadic pack
// Move the last element in if possible. Order of evaluation is well-defined
// for aggregate initialization, so there is no risk of copy-after-move
return std::array<std::decay_t<T>, size>{ (static_cast<void>(indexes), value)..., std::forward<T>(value) };
}
} // namespace detail
전달한 값을 복사하여 첫 번째 size - 1 인수를 생성합니다.여기서는 변수 매개 변수 팩 인덱스를 확장할 대상으로 사용합니다.팩에는 - 이 들어 (「 」「 」「 - 1 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」「 」 「 」 「 」 「 」 「 」 「 」「make_index_sequence
은 0, 2, ..., - 2 0, 1, 2, 3, ..., 크 - 2입입니다.그러나 값은 신경 쓰지 않습니다(따라서 컴파일러 경고를 잠재우기 위해 무효로 설정했습니다).매개 변수 팩 확장은 코드를 다음과 같은 수준으로 확장합니다(확장 크기 == 4).
return std::array<std::decay_t<T>, 4>{ (static_cast<void>(0), value), (static_cast<void>(1), value), (static_cast<void>(2), value), std::forward<T>(value) };
는 이러한 팩 합니다....
원하는 항목을 확장하고 쉼표 연산자를 사용하도록 보장합니다.괄호가 없으면 배열 초기화에 많은 인수를 전달하는 것처럼 보이지만 실제로는 인덱스를 평가하고, 빈 결과를 무시하고, 빈 결과를 무시하고, 값을 반환합니다. 이 값은 배열에 복사됩니다.
가 막지논쟁, 가부르것는라고 부르는 std::forward
은최적화입니다. on, 은 에서 사용됩니다.누군가 임시 std:: 문자열을 전달하고 "이것들 중 5개의 배열을 만들어라"라고 말하면, 우리는 5개의 복사본 대신 4개의 복사본과 1개의 이동을 원합니다. 그std::forward
우리가 이 일을 할 수 있도록 보장합니다.
헤더 및 일부 장치 테스트를 포함한 전체 코드:
#include <array>
#include <type_traits>
#include <utility>
namespace detail {
template<std::size_t size, typename T, std::size_t... indexes>
constexpr auto make_array_n_impl(T && value, std::index_sequence<indexes...>) {
// Use the comma operator to expand the variadic pack
// Move the last element in if possible. Order of evaluation is well-defined
// for aggregate initialization, so there is no risk of copy-after-move
return std::array<std::decay_t<T>, size>{ (static_cast<void>(indexes), value)..., std::forward<T>(value) };
}
} // namespace detail
template<typename T>
constexpr auto make_array_n(std::integral_constant<std::size_t, 0>, T &&) {
return std::array<std::decay_t<T>, 0>{};
}
template<std::size_t size, typename T>
constexpr auto make_array_n(std::integral_constant<std::size_t, size>, T && value) {
return detail::make_array_n_impl<size>(std::forward<T>(value), std::make_index_sequence<size - 1>{});
}
template<std::size_t size, typename T>
constexpr auto make_array_n(T && value) {
return make_array_n(std::integral_constant<std::size_t, size>{}, std::forward<T>(value));
}
struct non_copyable {
constexpr non_copyable() = default;
constexpr non_copyable(non_copyable const &) = delete;
constexpr non_copyable(non_copyable &&) = default;
};
int main() {
constexpr auto array_n = make_array_n<6>(5);
static_assert(std::is_same<std::decay_t<decltype(array_n)>::value_type, int>::value, "Incorrect type from make_array_n.");
static_assert(array_n.size() == 6, "Incorrect size from make_array_n.");
static_assert(array_n[3] == 5, "Incorrect values from make_array_n.");
constexpr auto array_non_copyable = make_array_n<1>(non_copyable{});
static_assert(array_non_copyable.size() == 1, "Incorrect array size of 1 for move-only types.");
constexpr auto array_empty = make_array_n<0>(2);
static_assert(array_empty.empty(), "Incorrect array size for empty array.");
constexpr auto array_non_copyable_empty = make_array_n<0>(non_copyable{});
static_assert(array_non_copyable_empty.empty(), "Incorrect array size for empty array of move-only.");
}
{}을(를) 사용하면 선언된 대로 요소를 할당하고 나머지 요소는 0으로 초기화됩니다.
없는 = {}
초기화하기 위해 내용이 정의되지 않았습니다.
연결한 페이지의 상태
명시적 배열 크기가 지정되었지만 더 짧은 초기화 목록이 지정된 경우 지정되지 않은 요소는 0으로 설정됩니다.
파일: 할 수 .이렇게 작은 어레이의 경우 차이는 무시할 수 있습니다. 시 을 수 .memcpy
수정 가능한 배열로 이동합니다.
배열을 공통 값으로 초기화하는 또 다른 방법은 다음과 같은 일련의 정의에서 요소 목록을 실제로 생성하는 것입니다.
#define DUP1( X ) ( X )
#define DUP2( X ) DUP1( X ), ( X )
#define DUP3( X ) DUP2( X ), ( X )
#define DUP4( X ) DUP3( X ), ( X )
#define DUP5( X ) DUP4( X ), ( X )
.
.
#define DUP100( X ) DUP99( X ), ( X )
#define DUPx( X, N ) DUP##N( X )
#define DUP( X, N ) DUPx( X, N )
어레이를 공통 값으로 쉽게 초기화할 수 있습니다.
#define LIST_MAX 6
static unsigned char List[ LIST_MAX ]= { DUP( 123, LIST_MAX ) };
참고: DUP에 대한 매개 변수의 매크로 대체를 활성화하기 위해 DUPx가 도입되었습니다.
단일 바이트 요소 배열의 경우 memset을 사용하여 모든 요소를 동일한 값으로 설정할 수 있습니다.
여기에 예가 있습니다.
가장 간단한 방법은 다음과 같습니다.std::array
▁the▁that▁template▁ 반환하는 함수 템플릿을 작성합니다.std::array
아래와 같이 전달된 인수로 모든 요소가 초기화됩니다.
C++11 버전
template<std::size_t N> std::array<int, N> make_array(int val)
{
std::array<int, N> tempArray{};
for(int &elem:tempArray)
{
elem = val;
}
return tempArray;
}
int main()
{
//---------------------V-------->number of elements
auto arr = make_array<8>(5);
//------------------------^---->value of element to be initialized with
//lets confirm if all objects have the expected value
for(const auto &elem: arr)
{
std::cout << elem << std::endl; //prints all 5
}
}
C++17 버전
C++17을 사용하여 추가할 수 있습니다.constexpr
함수 템플릿으로 변환하여 constexpr 컨텍스트에서 사용할 수 있도록 합니다.
//-----------------------------------------vvvvvvvvv--->added constexpr
template<std::size_t N> std::array<int, N> constexpr make_array(int val)
{
std::array<int, N> tempArray{};
for(int &elem:tempArray)
{
elem = val;
}
return tempArray;
}
int main()
{
//--vvvvvvvvv------------------------------>constexpr added
constexpr auto arr = make_array<8>(5);
for(const auto &elem: arr)
{
std::cout << elem << std::endl;
}
}
이니셜라이저를 사용하는 경우 구조체 또는 배열에 대해 지정되지 않은 값이 기본적으로 생성됩니다.int와 같은 원시적인 유형의 경우, 그것은 그것들이 0이 될 것이라는 것을 의미합니다.이것은 재귀적으로 적용됩니다. 배열을 포함하는 구조체 배열을 가질 수 있으며 첫 번째 구조체의 첫 번째 필드만 지정하면 나머지는 모두 0 및 기본 생성자로 초기화됩니다.
컴파일러는 아마도 최소한 손으로 할 수 있는 것만큼 좋은 초기화 코드를 생성할 것입니다.저는 가능하면 컴파일러가 초기화를 해주는 것을 선호합니다.
C++ 프로그래밍 언어 V4에서 Stroustrup은 내장된 배열보다 벡터 또는 Valarray를 사용할 것을 권장합니다.Valarrary를 사용하면 생성할 때 다음과 같은 특정 값으로 초기화할 수 있습니다.
valarray <int>seven7s=(7777777,7);
어레이 7 멤버 길이가 "7777777"인 초기화.
이것은 "일반적인 오래된 C" 배열 대신 C++ 데이터 구조를 사용하여 답을 구현하는 C++ 방법입니다.
저는 코드에서 C++'isms v'isms를 사용하기 위해 valarray를 사용하는 것으로 전환했습니다.
언급URL : https://stackoverflow.com/questions/1065774/initialization-of-all-elements-of-an-array-to-one-default-value-in-c
'programing' 카테고리의 다른 글
WPF 제목 표시줄 배경색 변경 (0) | 2023.05.27 |
---|---|
null 가능한 유형 및 3진수 연산자: '? 10: null'이 금지된 이유는 무엇입니까? (0) | 2023.05.27 |
SessionState와 ViewState의 차이점은 무엇입니까? (0) | 2023.05.22 |
macOS Catalina 10.15(베타) - ~/.bash_profile이 내 셸에서 소스되지 않는 이유는 무엇입니까? (0) | 2023.05.22 |
로지스틱 회귀 분석 파이썬 해결사 정의 (0) | 2023.05.22 |