programing tip

std :: queue :: pop이 값을 반환하지 않는 이유는 무엇입니까?

itbloger 2020. 8. 24. 07:53
반응형

std :: queue :: pop이 값을 반환하지 않는 이유는 무엇입니까?


페이지를 살펴 보았지만 동일한 이유를 알 수 없습니다. 거기에 언급되어 있습니다

"아무 값도 반환하지 않고 클라이언트가 front ()를 사용하여 큐의 맨 앞에있는 값을 검사하도록 요구하는 것이 더 합리적입니다."

그러나 front ()에서 요소를 검사하려면 해당 요소를 lvalue로 복사해야합니다. 예를 들어이 코드 세그먼트에서

std::queue<int> myqueue;
int myint;
int result;
std::cin >> myint;
myqueue.push (myint);

/ * 여기서는 결과에 할당 될 RHS에 임시가 생성되며, 참조로 반환되는 경우 팝 작업 후 결과가 유효하지 않게 렌더링됩니다. * /

result = myqueue.front();  //result.
std::cout << ' ' << result;
myqueue.pop();

다섯 번째 줄에서 cout 객체는 먼저 myqueue.front ()의 복사본을 만든 다음 결과에 할당합니다. 그래서 차이점은 무엇입니까, 팝 기능은 같은 일을 할 수 있습니다.


그래서 차이점은 무엇입니까, 팝 기능은 같은 일을 할 수 있습니다.

실제로 같은 일을 할 수있었습니다. 그렇지 않은 이유는 팝된 요소를 반환 한 팝이 예외가있을 때 안전하지 않기 때문입니다 (값으로 반환해야하므로 복사본을 생성해야 함).

이 시나리오를 고려하십시오 (순진한 / 만든 팝 구현으로 내 요점을 설명하기 위해).

template<class T>
class queue {
    T* elements;
    std::size_t top_position;
    // stuff here
    T pop()
    {
        auto x = elements[top_position];
        // TODO: call destructor for elements[top_position] here
        --top_position;  // alter queue state here
        return x;        // calls T(const T&) which may throw
    }

T의 복사 생성자가 반환되면 이미 큐의 상태를 변경했으며 ( top_position내 순진한 구현에서) 요소가 큐에서 제거되고 반환되지 않습니다. 모든 의도와 목적을 위해 (클라이언트 코드에서 예외를 포착하는 방법에 관계없이) 대기열 맨 위에있는 요소가 손실됩니다.

이 구현은 팝된 값이 필요하지 않은 경우에도 비효율적입니다 (즉, 아무도 사용하지 않을 요소의 복사본을 생성 함).

이는 두 개의 개별 작업 ( void popconst T& front())을 통해 안전하고 효율적으로 구현할 수 있습니다 .


링크 한 페이지가 질문에 대한 답변입니다.

관련 섹션 전체를 인용하려면 :

왜 pop ()이 value_type 대신 void를 반환하는지 궁금 할 것입니다. 즉, 단일 멤버 함수에서 두 요소를 결합하는 대신 큐 맨 앞의 요소를 검사하고 제거하기 위해 front () 및 pop ()을 사용해야하는 이유는 무엇입니까? 사실이 디자인에는 좋은 이유가 있습니다. pop ()이 앞쪽 요소를 반환하면 참조가 아닌 값으로 반환해야합니다. 참조로 반환하면 매달린 포인터가 생성됩니다. 그러나 값에 의한 반환은 비효율적입니다. 하나 이상의 중복 복사 생성자 호출이 필요합니다. pop ()이 효율적이고 정확한 방식으로 값을 반환하는 것은 불가능하기 때문에 값을 전혀 반환하지 않고 클라이언트가 front ()를 사용하여 값을 검사하도록 요구하는 것이 더 합리적입니다. 대기열의 앞.

C ++는 프로그래머가 작성해야하는 코드 라인 수에 비해 효율성을 염두에두고 설계되었습니다.


pop은 데이터 구조에서 제거되므로 제거 된 값에 대한 참조를 반환 할 수 없습니다. 참조가 무엇을 참조해야합니까? 값으로 반환 할 수 있지만 pop의 결과가 어디에도 저장되지 않으면 어떻게 될까요? 그러면 불필요하게 값을 복사하는 데 시간이 낭비됩니다.


현재 구현에서는 유효합니다.

int &result = myqueue.front();
std::cout << result;
myqueue.pop();

pop이 다음과 같은 참조를 반환하는 경우 :

value_type& pop();

그러면 참조가 더 이상 유효하지 않기 때문에 다음 코드가 충돌 할 수 있습니다.

int &result = myqueue.pop();
std::cout << result;

반면에 값을 직접 반환하는 경우 :

value_type pop();

그런 다음이 코드가 작동하려면 복사를 수행해야합니다. 이는 효율성이 떨어집니다.

int result = myqueue.pop();
std::cout << result;

Starting from C++11 it would possible to archive desired behavior using move semantics. Like pop_and_move. So copy constructor will not be called, and performance will depend on move constructor only.


You can totally do this:

std::cout << ' ' << myqueue.front();

Or, if you want the value in a variable, use a reference:

const auto &result = myqueue.front();
if (result > whatever) do_whatever();
std::cout << ' ' << result;

Next to that: the wording 'more sensible' is a subjective form of 'we looked into usage patterns and found more need for a split'. (Rest assured: the C++ language is not evolving lightly...)


I think the best solution would be to add something like

std::queue::pop_and_store(value_type& value);

where value will receive the popped value.

The advantage is that it could be implemented using a move assignment operator, while using front + pop will make a copy.

참고URL : https://stackoverflow.com/questions/25035691/why-doesnt-stdqueuepop-return-value

반응형