for 루프에서 std :: size_t 또는 int를 사용해야합니까?
std::size_t
대신 루프와 물건에 사용해야 int
합니까? 예를 들어 :
#include <cstdint>
int main()
{
for (std::size_t i = 0; i < 10; ++i) {
// std::size_t OK here? Or should I use, say, unsigned int instead?
}
}
일반적으로 사용시기에 관한 모범 사례는 무엇 std::size_t
입니까?
경험상 좋은 규칙은 루프 조건에서 자연스럽게 다른 것과 비교해야하는 모든 것입니다 std::size_t
.
std::size_t
는 sizeof
식 의 유형이며 C ++에서 모든 객체 (배열 포함)의 최대 크기를 표현할 수 있음을 보장합니다. 확장하여 배열 인덱스에 대해서도 충분히 클 수 있으므로 배열에 대한 인덱스 별 루프의 자연스러운 유형입니다.
숫자를 세는 것이라면 그 숫자를 보유한 변수의 유형을 사용하는 것이 더 자연 스럽거나 기계의 크기가 자연 스럽기 때문에 ( int
또는 unsigned int
충분히 큰 경우) 더 자연 스럽습니다.
size_t
sizeof
연산자 의 결과 유형입니다 .
size_t
배열에서 크기 또는 색인을 모델링하는 변수에 사용하십시오 . size_t
의미를 전달합니다. 즉, 다른 정수가 아니라 크기 또는 바이트 단위의 크기를 나타냅니다.
또한 size_t
크기를 바이트 단위로 나타내는 데 사용하면 코드를 이식성있게 만들 수 있습니다.
size_t
유형은 지정하기위한 것입니다 크기 는 문자열의 길이를 취득하고 각 문자를 처리하는, 예를 들어, 그것을 사용하는 천연 그래서 무언가를 :
for (size_t i = 0, max = strlen (str); i < max; i++)
doSomethingWith (str[i]);
당신은 않는 이 부호없는 형식이기 때문에, 물론 경계 조건에 대한 조심해야합니다. (비록 최대는 일반적으로 크기 때문에 맨 끝에서 경계는 일반적으로 중요하지 않다 입니다 거기에 도착하는 것이 가능). 대부분의 사람들 int
은 그 용량을 초과 할만큼 충분히 큰 구조 나 배열을 거의 갖지 않기 때문에 그런 종류의 것을 위해 단지를 사용 합니다 int
.
그러나 다음과 같은 것을 조심하십시오.
for (size_t i = strlen (str) - 1; i >= 0; i--)
부호없는 값의 줄 바꿈 동작으로 인해 무한 루프가 발생합니다 (컴파일러가 이것에 대해 경고하는 것을 보았지만). 이것은 또한 약간 완화 될 수 있습니다 (약간 이해하기는 어렵지만 적어도 포장 문제에 대한 면역) :
for (size_t i = strlen (str); i-- > 0; )
연속 조건 후 체크 부작용으로 감소를 이동시킴으로써,이 값에 연속 대한 검사 수행 전에 (어떤 이유에서 루프가 실행 감소를 여전히 루프 내부의 감소 값을 사용 len .. 1
하는 대신 len-1 .. 0
).
정의 size_t
에 따라 sizeof
연산자 의 결과입니다 . size_t
크기를 참조하기 위해 만들어졌습니다.
당신이 무언가를하는 횟수 (예에서 10)는 크기에 관한 것이 아니므로 왜 사용 size_t
합니까? int
또는 unsigned int
이어야합니다.
물론 i
루프 내부에서 수행하는 작업과 관련이 있습니다 . unsigned int
예를 들어을 사용 하는 함수에 전달하면을 선택하십시오 unsigned int
.
어쨌든 암시 적 유형 변환을 피하는 것이 좋습니다. 모든 유형 변환을 명시 적으로 만드십시오.
size_t
등의 문자열의 길이, 포인터가 소요 바이트의 양 또한 플랫폼에서 휴대용입니다 - - 항목의 크기 치수를 지정하는 매우 읽을 수있는 방법은 당신이 64 비트를 찾아 시스템 기능과 함께 잘 모두 행동하라를 32 비트 것 size_t
- 뭔가 unsigned int
예를 들어, 사용시기를 수행하지 않을 수 있습니다 (unsigned long
C 스타일 배열 인덱싱 / 카운팅에는 std :: size_t를 사용하십시오.
STL 컨테이너의 경우 (예를 들어) vector<int>::size_type
벡터 요소를 인덱싱하고 계산하는 데 사용해야합니다.
실제로는 일반적으로 서명되지 않은 정수이지만 특히 사용자 지정 할당자를 사용할 때는 보장되지 않습니다.
곧 대부분의 컴퓨터는 수십억 개의 요소가있는 컨테이너에서 작동하는 프로그램을 실행하는 64 비트 OS가 포함 된 64 비트 아키텍처가 될 것입니다. 그럼 당신은 있어야 사용 size_t
대신 int
, 루프 인덱스로 그렇지 않으면 지수는 것이다 랩 어라운드 2 ^ 32시 : 32 비트 및 64 비트 시스템에 번째 요소.
미래를 준비하십시오!
짧은 답변:
거의 없다
긴 대답 :
32 비트 시스템에서 2GB보다 큰 char 벡터가 필요할 때마다 다른 모든 사용 사례에서 부호없는 유형을 사용하는 것이 부호없는 유형을 사용하는 것보다 훨씬 안전합니다.
예:
std::vector<A> data;
[...]
// calculate the index that should be used;
size_t i = calc_index(param1, param2);
// doing calculations close to the underflow of an integer is already dangerous
// do some bounds checking
if( i - 1 < 0 ) {
// always false, because 0-1 on unsigned creates an underflow
return LEFT_BORDER;
} else if( i >= data.size() - 1 ) {
// if i already had an underflow, this becomes true
return RIGHT_BORDER;
}
// now you have a bug that is very hard to track, because you never
// get an exception or anything anymore, to detect that you actually
// return the false border case.
return calc_something(data[i-1], data[i], data[i+1]);
의 서명 상당 size_t
하다 ptrdiff_t
하지 int
. 그러나 int
size_t보다 대부분의 경우 여전히 사용하는 것이 좋습니다. ptrdiff_t
인 long
32 및 64 비트 시스템.
This means that you always have to convert to and from size_t whenever you interact with a std::containers, which not very beautiful. But on a going native conference the authors of c++ mentioned that designing std::vector with an unsigned size_t was a mistake.
If your compiler gives you warnings on implicit conversions from ptrdiff_t to size_t, you can make it explicit with constructor syntax:
calc_something(data[size_t(i-1)], data[size_t(i)], data[size_t(i+1)]);
if just want to iterate a collection, without bounds cheking, use range based for:
for(const auto& d : data) {
[...]
}
here some words from Bjarne Stroustrup (C++ author) at going native
For some people this signed/unsigned design error in the STL is reason enough, to not use the std::vector, but instead an own implementation.
When using size_t be careful with the following expression
size_t i = containner.find("mytoken");
size_t x = 99;
if (i-x>-1 && i+x < containner.size()) {
cout << containner[i-x] << " " << containner[i+x] << endl;
}
You will get false in the if expression regardless of what value you have for x. It took me several days to realize this (the code is so simple that I did not do unit test), although it only take a few minutes to figure the source of the problem. Not sure it is better to do a cast or use zero.
if ((int)(i-x) > -1 or (i-x) >= 0)
Both ways should work. Here is my test run
size_t i = 5;
cerr << "i-7=" << i-7 << " (int)(i-7)=" << (int)(i-7) << endl;
The output: i-7=18446744073709551614 (int)(i-7)=-2
I would like other's comments.
size_t is returned by various libraries to indicate that the size of that container is non-zero. You use it when you get once back :0
However, in the your example above looping on a size_t is a potential bug. Consider the following:
for (size_t i = thing.size(); i >= 0; --i) {
// this will never terminate because size_t is a typedef for
// unsigned int which can not be negative by definition
// therefore i will always be >= 0
printf("the never ending story. la la la la");
}
the use of unsigned integers has the potential to create these types of subtle issues. Therefore imho I prefer to use size_t only when I interact with containers/types that require it.
size_t
is an unsigned type that can hold maximum integer value for your architecture, so it is protected from integer overflows due to sign (signed int 0x7FFFFFFF
incremented by 1 will give you -1) or short size (unsigned short int 0xFFFF incremented by 1 will give you 0).
It is mainly used in array indexing/loops/address arithmetic and so on. Functions like memset()
and alike accept size_t
only, because theoretically you may have a block of memory of size 2^32-1
(on 32bit platform).
For such simple loops don't bother and use just int.
size_t is an unsigned integral type, that can represent the largest integer on you system. Only use it if you need very large arrays,matrices etc.
Some functions return an size_t and your compiler will warn you if you try to do comparisons.
Avoid that by using a the appropriate signed/unsigned datatype or simply typecast for a fast hack.
size_t is unsigned int. so whenever you want unsigned int you can use it.
I use it when i want to specify size of the array , counter ect...
void * operator new (size_t size); is a good use of it.
참고URL : https://stackoverflow.com/questions/1951519/should-i-use-stdsize-t-or-int-in-my-for-loops
'Programing' 카테고리의 다른 글
SQL Server 2005의 한 명령문에서 두 개의 테이블을 업데이트하는 방법은 무엇입니까? (0) | 2020.05.18 |
---|---|
git stash가 추가 된 파일을 덮어 쓰도록 강제 (0) | 2020.05.18 |
UIImage 배열을 동영상으로 내보내려면 어떻게합니까? (0) | 2020.05.18 |
자바 스크립트에서 [] .slice.call에 대한 설명은 무엇입니까? (0) | 2020.05.18 |
Windows 배치 파일에서 시스템 환경 변수를 설정 하시겠습니까? (0) | 2020.05.18 |