2014-02-27 4 views
10

기본적으로 std::stack의 "기본 컨테이너"는 std::deque입니다. 따라서 어떤 std::deque에 대한 정의되지 않은 동작은 std::stack에 대해 정의되지 않은 동작입니다. cppreference 및 기타 사이트에서는 멤버 함수의 동작을 설명 할 때 "효과적으로"라는 용어를 사용합니다. 나는 그것이 모든 의도와 목적을위한 것이라고 생각합니다. 따라서 top()pop()을 호출하는 것은 back()pop_back()을 호출하는 것과 동일하며 빈 컨테이너에서 호출하는 것은 정의되지 않은 동작입니다.STL에서 정의되지 않은 동작이 허용되는 이유는 무엇입니까?

내 이해에서, 그것이 정의되지 않은 이유는 no-throw 보증을 유지하는 것입니다. 내 논리에 따르면 std::vector에 대한 operator[]은 no-throw 보증을 가지고 있으며 컨테이너 크기가 N보다 크지 만 at()은 강력한 보증을 갖고 정의되지 않은 동작이며 n이 범위를 벗어난 경우 std::out_of_range을 던졌습니다.

내 질문에, 가능성이 정의되지 않은 동작을 가지고 있고 강력한 보장을 가지고 있지만 대신 예외를 던지거나 던지기 보증을하는 몇 가지 이유에 대한 근거는 무엇입니까?

답변

14

정의되지 않은 동작이 허용되는 경우 효율성을 이유로 이 보통입니다.

범위를 벗어난 배열에 액세스 할 때 표준이 지정되면 구현에서 강제로 인덱스가 경계에 있는지 확인해야합니다. 벡터는 동적 배열의 래퍼 일뿐입니다.

다른 경우에는 구현을 자유롭게하기 위해 동작을 정의 할 수 없습니다. 하지만 이는 실제로 효율성에 관한 것입니다 (일부 구현 전략은 다른 시스템보다 효율적이기 때문에 C++은 원하는 경우 가장 효율적인 전략을 선택하기 위해 구현 자에게 맡깁니다).

2

Herb Sutter에 따르면 현저한 이유는 효율성입니다. 그는이 표준이 operator[]의 예외 사양이나 바운드 검사가 필요한지 여부에 대한 요구 사항을 부과하지 않는다고 설명합니다. 이것은 구현에 달려 있습니다. 한편

vector<T>::operator[]()이 허용됩니다,하지만 은 경계 검사를 수행하는 데 필요한. 검사 범위에 대해 아무것도 말한다 operator[]()의 표준 사양의 표현 의 호흡이 아니다,하지만 둘 다 너무 표준 라이브러리 구현 이 operator[]()에 경계가 검사 추가 무료이며, 예외 사양이 모든 요구 사항이있다 , 너무. 따라서 operator[]()을 사용하여 벡터에없는 요소를 요청하면 자신이 이고 표준에서는 이 무엇이 발생하는지 보증하지 않습니다 (표준 라이브러리 구현 설명서 일 수도 있음). 프로그램이 즉시 중단 될 수 있습니다. operator[]()에 대한 호출이 예외를 throw 할 수 있습니다. 또는 이 작동하지 않는 것처럼 보일 수 있으며 때로는 신비하게 실패합니다.

경계 검사를 통해 많은 공통적 인 문제를 방지 할 수 있다고 가정하면 경계 검사를 수행하는 데 operator[]()이 필요하지 않은 이유는 무엇입니까? 짧은 대답은 다음과 같습니다. 효율성.항상 경계를 확인하면 (심지어 경미한) 성능 오버 헤드가 모든 프로그램에서 발생하며 심지어 이 경계를 위반하지 않습니다. C++의 정신에는 및 큰 것으로 여러분이 사용하지 않는 것에 대해 비용을 지불 할 필요가 없다는 내용의 담기가 포함되어 있으므로 operator[]()에 대해서는 경계 검사가 필요하지 않습니다. 이 경우 우리는 에 효율성을 원하는 또 다른 이유가 있습니다. 벡터는 내장 배열 대신 을 사용해야하므로 경계 맞춤 검사를 수행하지 않는 내장 배열로 효율적인 이어야합니다. 범위가 확인되도록 이 되려면 at()을 대신 사용하십시오.

은 성능 이점에 대해 궁금하다면,이 두 가지 질문을 참조하십시오

  1. ::std::vector::at() vs operator[] << surprising results!! 5 to 10 times slower/faster!
  2. vector::at vs. vector::operator[]

합의가 operator[]이 더 효율적입니다 것 같다 (이후 std::vector은 동적 배열을 감싸는 래퍼 일 뿐이므로 operator[]은 호출하는 것처럼 효율적이어야합니다. 어레이에서). 그리고 Herb Sutter는 컴파일러 - 벤더에 따라 예외가 없는지 여부를 제안하는 것으로 보입니다.

관련 문제