방금 C ++에 들어가기 시작했고 좋은 습관을 고르고 싶습니다. 연산자를 int
사용하여 유형의 배열을 방금 할당 한 경우 new
직접 루프하지 않고 어떻게 0으로 초기화 할 수 있습니까? 그냥 사용해야 memset
합니까? “C ++”방법이 있습니까?
&vector[0]
.
방금 C ++에 들어가기 시작했고 좋은 습관을 고르고 싶습니다. 연산자를 int
사용하여 유형의 배열을 방금 할당 한 경우 new
직접 루프하지 않고 어떻게 0으로 초기화 할 수 있습니까? 그냥 사용해야 memset
합니까? “C ++”방법이 있습니까?
&vector[0]
.
답변:
놀랍게도 C ++의 거의 알려지지 않은 기능이지만 (아직 아무도 이것을 대답으로 제공하지 않았다는 사실에 의해 입증 됨) 실제로 배열의 값을 초기화하는 특수 구문이 있습니다.
new int[10]();
이 점에 유의 해야한다 당신이 할 수없는, 예를 들어, 사용 - 빈 괄호를 사용 (0)
하거나 다른 것 (인이 값 초기화에만 유용 이유).
이것은 ISO C ++ 03 5.3.4 [expr.new] / 15에서 명시 적으로 허용됩니다.
유형의 객체를 생성하는 새로운 표현식
T
은 다음과 같이 해당 객체를 초기화합니다....
- 새 이니셜 라이저가 양식
()
인 경우 항목은 값으로 초기화됩니다 (8.5).
이 유형은 허용되는 유형을 제한하지 않지만 (expression-list)
양식은 배열 유형을 허용하지 않도록 동일한 섹션의 추가 규칙에 의해 명시 적으로 제한됩니다.
new int[10] {}
. 다음과 같이 초기화 할 값을 제공 할 수도 있습니다.new int[10] {1,2,3}
실제로 std :: vector가 아닌 배열을 원한다고 가정하면 "C ++ 방식"은 다음과 같습니다.
#include <algorithm>
int* array = new int[n]; // Assuming "n" is a pre-existing variable
std::fill_n(array, n, 0);
그러나 후드 아래에서 이것은 실제로 각 요소를 0에 할당하는 루프 일뿐입니다 (하드웨어 수준 지원을 가진 특수 아키텍처를 제외하고는 실제로 다른 방법은 없습니다).
내장 형식의 배열을 할당하는 방법에는 여러 가지가 있으며 이러한 방법은 모두 올바른지 선택해야합니다.
루프의 모든 요소를 수동으로 초기화
int* p = new int[10];
for (int i = 0; i < 10; i++)
{
p[i] = 0;
}
std::memset
기능 사용<cstring>
int* p = new int[10];
std::memset(p, 0, sizeof(int) * 10);
의 std::fill_n
알고리즘 사용<algorithm>
int* p = new int[10];
std::fill_n(p, 10, 0);
std::vector
컨테이너 사용
std::vector<int> v(10); // elements zero'ed
C ++ 0x가 사용 가능한 경우 이니셜 라이저 목록 기능 사용
int a[] = { 1, 2, 3 }; // 3-element static size array
vector<int> v = { 1, 2, 3 }; // 3-element array but vector is resizeable in runtime
int array[SIZE] ={1,2,3,4,5,6,7};
표기법을, 내가 사용할 수있는 void rotateArray(int (& input)[SIZE], unsigned int k);
첫 번째 규칙을 사용하면 내 함수 선언 될 것이다, 무엇을 할 것인가? 어떠한 제안?
std::memset
가 잘못되었다는 것이 두렵습니다. 10을 전달하면 바이트 수를 예상하는 것 같습니다 -en.cppreference.com/w/cpp/string/byte/memset 참조하십시오 . (이것이 가능한 경우 저수준 구조를 피해야하는 이유를 잘 보여줍니다.)
할당하는 메모리가 유용한 생성자를 가진 클래스 인 경우 new 연산자는 해당 생성자를 호출하고 객체를 초기화 된 상태로 둡니다.
그러나 POD 또는 객체의 상태를 초기화하는 생성자가없는 것을 할당하는 경우 한 번의 작업으로 new 연산자로 메모리를 할당하고 해당 메모리를 초기화 할 수 없습니다. 그러나 몇 가지 옵션이 있습니다.
1) 대신 스택 변수를 사용하십시오. 다음 과 같이 한 단계로 할당하고 기본값을 초기화 할 수 있습니다 .
int vals[100] = {0}; // first element is a matter of style
2) 사용하십시오 memset()
. 할당하려는 객체가 POD 가 아닌 경우 memsetting하는 것은 나쁜 생각입니다. 한 가지 구체적인 예는 가상 함수가있는 클래스를 memset하면 vtable을 날려 버리고 객체를 사용할 수없는 상태로 유지하는 것입니다.
3) 많은 운영 체제에는 원하는 것을 수행하는 호출이 있습니다. 힙에 할당하고 데이터를 무언가로 초기화하십시오. Windows 예제는VirtualAlloc()
4) 이것이 가장 좋은 옵션입니다. 메모리를 직접 관리하지 않아도됩니다. STL 컨테이너를 사용하면 한 번의 실패로 모든 것을 할당하고 초기화하는 것을 포함하여 원시 메모리로 할 수있는 모든 작업을 수행 할 수 있습니다.
std::vector<int> myInts(100, 0); // creates a vector of 100 ints, all set to zero
예 :
std::vector<int> vec(SIZE, 0);
동적으로 할당 된 배열 대신 벡터를 사용하십시오. 이점은 배열을 명시 적으로 삭제하지 않아도되며 (벡터가 범위를 벗어날 때 삭제됨) 예외가 발생하더라도 메모리가 자동으로 삭제됩니다.
편집 : 아래 주석을 읽는 것을 귀찮게하지 않는 사람들의 추가 드라이브 바이 다운을 피하려면이 대답이 벡터가 항상 올바른 답 이라고 말하는 것은 아닙니다 . 그러나 "수동으로"배열보다 C ++ 방식이 더 확실합니다.
이제 C ++ 11에는 std :: array가있어 일정한 크기의 배열 (vs 벡터가 자랄 수 있음)을 모델링합니다. 동적으로 할당 된 배열을 관리하는 std :: unique_ptr도 있습니다 (이 질문에 대한 다른 답변에서 답변 된 것처럼 초기화와 결합 할 수 있음). 그것들 중 하나는 IMHO 배열에 대한 포인터를 수동으로 처리하는 것보다 더 C ++ 방식입니다.
std::vector
동적으로 할당 된 배열 대신 항상 사용해야 합니까? 벡터보다 배열을 사용하면 어떤 이점이 있습니까?
std::vector
.
vector
문맥에 관계없이 어디든지 고집하는 것을 "C ++로 Java 코드 작성"이라고합니다.
std::fill
한 가지 방법입니다. 두 개의 반복자와 영역을 채울 값을 가져옵니다. 즉, for 루프는 더 C ++ 방식 일 것입니다.
기본 정수 유형의 배열을 구체적으로 0으로 설정하면 memset
눈썹을 올릴 수 있지만 좋습니다. calloc
캐스트 때문에 C ++에서 사용하는 것이 약간 불편하지만을 고려하십시오 .
내 부분에서는 거의 항상 루프를 사용합니다.
(나는 사람들의 의도를 추측하는 것을 좋아하지 않지만 std::vector
모든 것이 동등하고을 사용하는 것보다 낫다는 것은 사실입니다 new[]
.)
당신은 항상 memset을 사용할 수 있습니다 :
int myArray[10];
memset( myArray, 0, 10 * sizeof( int ));
memset
하지만 이것이 문제에 접근하는 C ++ 방법인지 확실하지 않습니다.
10 * sizeof( *myArray )
보다 문서화되고 변경이 방지 10 * sizeof( int )
됩니다.