簡體   English   中英

為什么deque :: erase()會調用賦值運算符?

[英]Why does deque::erase() invoke assignment operator?

正如標題所說,為什么deque在erase()期間調用包含類型的賦值運算符? 我可以理解為什么向量可能因為向量中的元素在連續的內存中,但由於deque不能保證連續的內存,為什么它會在刪除某些元素時嘗試移動它的元素。

此代碼無法編譯,因為我的Contained類型的賦值運算符被刪除,並且它沒有移動構造函數。

#include <deque>

class Contained
{
public:
    Contained() = default;
    ~Contained() { }
    Contained(const Contained&) = delete;
    Contained& operator=(const Contained&) = delete;
};

class Container
{
public:
    Container()
    {
        for(int i = 0; i < 5; i++) { m_containerDS.emplace_back(); }
    }

    ~Container() { }

    void clear() 
    { 
        m_containerDS.erase(m_containerDS.begin(), m_containerDS.end()); 
    }

private:
    std::deque<Contained> m_containerDS;
};


int main()
{
    return 0;
}

MSVC編譯器發出以下錯誤消息:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xutility(2527): error C2280: 'Contained &Contained::operator =(const Contained &)' : attempting to reference a deleted function
1>          ConsoleApplication13.cpp(12) : see declaration of 'Contained::operator ='
1>          C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xutility(2548) : see reference to function template instantiation '_BidIt2 std::_Move_backward<_BidIt1,_BidIt2>(_BidIt1,_BidIt1,_BidIt2,std::_Nonscalar_ptr_iterator_tag)' being compiled
1>          with
1>          [
1>              _BidIt2=std::_Deque_iterator<std::_Deque_val<std::_Deque_simple_types<Contained>>>
1>  ,            _BidIt1=std::_Deque_iterator<std::_Deque_val<std::_Deque_simple_types<Contained>>>
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\deque(1622) : see reference to function template instantiation '_BidIt2 std::_Move_backward<std::_Deque_iterator<std::_Deque_val<std::_Deque_simple_types<Contained>>>,std::_Deque_iterator<std::_Deque_val<std::_Deque_simple_types<Contained>>>>(_BidIt1,_BidIt1,_BidIt2)' being compiled
1>          with
1>          [
1>              _BidIt2=std::_Deque_iterator<std::_Deque_val<std::_Deque_simple_types<Contained>>>
1>  ,            _BidIt1=std::_Deque_iterator<std::_Deque_val<std::_Deque_simple_types<Contained>>>
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\deque(1601) : while compiling class template member function 'std::_Deque_iterator<std::_Deque_val<std::_Deque_simple_types<Contained>>> std::deque<Contained,std::allocator<_Ty>>::erase(std::_Deque_const_iterator<std::_Deque_val<std::_Deque_simple_types<_Ty>>>,std::_Deque_const_iterator<std::_Deque_val<std::_Deque_simple_types<_Ty>>>)'
1>          with
1>          [
1>              _Ty=Contained
1>          ]
1>          ConsoleApplication13.cpp(27) : see reference to function template instantiation 'std::_Deque_iterator<std::_Deque_val<std::_Deque_simple_types<Contained>>> std::deque<Contained,std::allocator<_Ty>>::erase(std::_Deque_const_iterator<std::_Deque_val<std::_Deque_simple_types<_Ty>>>,std::_Deque_const_iterator<std::_Deque_val<std::_Deque_simple_types<_Ty>>>)' being compiled
1>          with
1>          [
1>              _Ty=Contained
1>          ]
1>          ConsoleApplication13.cpp(31) : see reference to class template instantiation 'std::deque<Contained,std::allocator<_Ty>>' being compiled
1>          with
1>          [
1>              _Ty=Contained
1>          ]

簡短回答:因為

類型要求

-T必須滿足MoveAssignable的要求。

答案很長:即使std::deque沒有提供連續內存的要求,它仍然需要提供一個恆定的完整性operator[] 這就是它必須移動元素的原因。

這是因為std :: deque經常被實現為環形緩沖區,而環形緩沖區又經常被實現為單片內存緩沖區。 這意味着當您從雙端隊列中刪除元素時,如果已刪除的元素不在序列的結尾或開頭,則可能需要移動一些元素。 這是插圖:

    V buffer begins here                    V buffer ends here
1. [ ] [.] [.] [.] [.] [.] [.] [.] [ ] [ ] [ ]
        ^first element          ^last element

2. [ ] [.] [.] [.] [.] [.] [.] [.] [ ] [ ] [ ]
                ^ you want to remove this element.

                <= these elements should be moved
                    V   V   V   V
3. [ ] [.] [.] [ ] [:] [:] [:] [:] [ ] [ ] [ ]
                ^ element have been removed.

實際上,只有在類型沒有移動運算符時才使用賦值運算符。 因此,如果您在課程中添加以下行,那么所有內容都可以正常編譯:

Contained& operator=(Contained&&) = default;

更新:似乎我錯了,因為大多數STL實現現在使用動態數組的一些變體,而不是環形緩沖區。 但是,它們是數組,如果從數組中間刪除了一個元素,則需要移動元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM