2010-05-03 2 views
9

빠른 배경
저는 무료/지루한 시간에 C++로 놀고있는 Java 개발자입니다.왜 pop()이 인수를 취해야합니까?

C에서
는 ++, 자주 팝업 참조에 의해 인수를 복용 참조 서문 :

void pop(Item& removed); 

나는 당신이 제거 된 것과 매개 변수 "를 입력"을 좋은 것으로 알고 있습니다. 그건 나에게 의미가있다. 이렇게하면 맨 위 항목을 제거하도록 요청한 사람이 제거 된 항목을 볼 수 있습니다. 그 결과, 아이템, 또는으로 NULL :

Item pop() throws StackException; 

이 방법은, 우리가 하나 돌아 팝업 후 : 나는 자바에서이 작업을 수행하는 경우

그러나, 나는 이런 식으로 뭔가를 할 거라고 예외가 발생합니다.

내 C++ 교과서는 위의 예를 보여 주지만 인수가없는 스택 구현 (예 : stl stack)을 많이 볼 수 있습니다.

질문에 대한 답변
C++에서 pop 함수를 구현하는 방법은 무엇입니까?

보너스
왜?

답변

26

질문에 답하려면 : C++에서 pop 함수를 구현하면 안됩니다. STL에 의해 이미 구현 되었기 때문입니다. 컨테이너 어댑터는 top 메서드를 사용하여 스택의 맨 위 요소에 대한 참조를 가져오고 pop 메서드는 맨 위 요소를 제거합니다. 요청한대로 pop 메서드 만 사용하여 두 작업을 모두 수행 할 수는 없습니다.

왜 그런 식으로해야합니까?

  1. 예외 안전 : 허브 셔터는 GotW #82에서 문제의 좋은 설명을 제공합니다.
  2. 단일 책임 원칙 : GotW # 82에서도 언급 됨. top은 한 가지 책임을지고 pop은 다른 것을 담당합니다.
  3. 필요없는 것을 지불하지 마십시오 : 일부 코드의 경우 요소의 (잠재적으로 값 비싼) 복사본을 만들지 않고 상단 요소를 검사하여 팝업 할 수 있습니다. (이것은 SGI STL 문서에 언급되어있다.)

추가 비용이 작업을 수행 할 수있는 요소의 사본을 얻을하고자하는 모든 코드 : 또한

Foo f(s.top()); 
s.pop(); 

, this discussion은 흥미로운 일이 될 수 있습니다.

값을 반환하기 위해 pop을 구현하려는 경우 값으로 반환할지 아니면 out 매개 변수에 쓰는지는 중요하지 않습니다.대부분의 컴파일러는 RVO을 구현합니다.이 방법은 매개 변수로 복사 방법과 마찬가지로 효율적으로 반환 방법을 최적화합니다. 이 중 하나는 top() 또는 front()를 사용하여 객체를 검사하는 것보다 효율적이지 않을 것입니다.이 경우에는 복사가 전혀 수행되지 않기 때문입니다.

+0

굉장 링크, 고맙습니다. 그래서 C++에서 pop()을 구현하라는 인터뷰에서 물어 보면 ... 내가 대답해야할까요? : p – Stephano

+2

+1 ...하지만 "C++에서 pop 함수를 구현하면 표준 컨테이너 인터페이스를 따라야합니다." – Potatoswatter

+1

@Stephano : 면접관이 원하는대로 달려 있습니다. 어떤 것은'std :: stack'에 대해서 알고 있고'push','top','pop' 메쏘드를 가지고 있다는 것을 알고있을 것입니다. 일부는 고정 길이 배열을 사용하여 자신의 스택을 구현할 수 있는지 확인하기 위해 스택을 구현해야 할 수도 있습니다. – Dan

4

Java 접근법의 문제점은 해당 pop() 메소드가 요소를 제거하고 요소를 반환하는 적어도 두 가지 효과가 있다는 것입니다. 이것은 소프트웨어 설계의 단일 책임 원칙에 위배되며, 이는 다시 디자인 복잡성 및 기타 문제의 문을 엽니 다. 그것은 또한 성능 저하를 의미합니다.

사물의 STL 방식에서는 아이디어가 때로는 pop() 때 갑자기 나타나지 않는 항목에 관심이 있습니다. 상위 요소를 제거하는 효과 만 원할뿐입니다. 함수가 요소를 반환하고 무시하면 낭비됩니다.

두 개의 오버로드를 제공하는 경우 하나는 참조를 취하고 다른 하나는 리턴하지 않는 요소를 사용자가 선택할 수있게합니다. 통화 성능이 최적화됩니다.

STL과는 pop() 기능에 과부하가 걸리지 않고 오히려 두 가지 기능으로 다음을 나눕니다합니다 (std::stack 어댑터의 경우 또는 top()) back()pop(). back() 함수는 요소를 반환하지만 pop() 함수는 요소를 반환합니다. 나는 C++에서이 구문을 사용하는 볼 수 있습니다

+1

'top'은'front'이 아니다. –

+1

과'top'은'back'을 호출한다. – Potatoswatter

+4

하나의 원자 적 연산으로 두 가지 효과가있는 함수가 소프트웨어 설계의 단일 책임 원칙에 위배되지 않는다. –

0

유일한 이유 : 당신이 일어나고 불필요한 복사에 대해 걱정하는 경우

void pop(Item& removed); 

이다. 당신이 Item을 반환하는 경우

, 그것은 수도 비용이 될 수있는 오브젝트의 추가 사본이 필요합니다.

실제로 C++ 컴파일러는 elion 복사 기능이 뛰어나며 (거의 대부분 최적화 기능을 해제하여 컴파일 할 때조차도) 항상 반환 값 최적화를 구현합니다. 이는 점을 부추 기고 단순한 "return by value 경우에 따라 이 더 빨리이됩니다. 당신이 조기 최적화에 있다면

는하지만, 당신이 "반환"매개 변수에 대해 주장 할 수있다 (당신이 있다면 실제로는 그것을 할 것입니다 경우에도 컴파일러, 사본을 멀리 최적화 할 수 있다는 걱정) 참조 매개 변수에 지정하여 무언가 같이

자세한 내용은 here

0

IMO, C++에서 자바의 pop 함수의 eqivalent에 대한 좋은 서명은 다음과 같습니다 옵션 유형을 사용하면 무언가를 반환하는 가장 좋은 방법입니다

boost::optional<Item> pop(); 

그 수도 있고 사용하지 못할 수도 있습니다.

1

C++ 0x를 사용하면 모든 것을 다시 어렵게 만듭니다.

stack.pop(item); // move top data to item without copying 

이 가능하게

효율적 스택으로부터 최상위 요소를 이동한다. 반면에

item = stack.top(); // make a copy of the top element 
stack.pop(); // delete top element 

은 이러한 최적화를 허용하지 않습니다.

+0

'item = std :: move (stack.top()); stack.pop();'는 효율적으로 작동합니다. 흥미로운 점은 C++ 03 (예외 안전성)에서이 디자인의 주된 이유는 더 이상 C++ 11의 경우가 아니라는 것입니다 (이동 생성자가 throw되지 않아야 함). – Mankarse

관련 문제