2016-08-12 94 views
2
#include <deque> 
#include <vector> 

struct A 
{ 
    A(int* const p) : m_P(p) {} 
    A(A&& rhs)  : m_P(rhs.m_P) { rhs.m_P = nullptr; } 
    A& operator=(A&& rhs) { delete m_P; m_P = rhs.m_P; rhs.m_P = nullptr; } 
    ~A() { delete m_P; } 

    A(A const& rhs)   = delete; 
    A& operator=(A const& rhs) = delete; 

    int* m_P; 
}; 

int main() 
{ 
#ifdef DDDEQUE 
    std::vector<std::pair<int, std::deque<A> > > vd; 
    vd.emplace(vd.end(), 1, std::deque<A>()); 
#endif // #ifdef DDDEQUE 

    std::vector<std::pair<int, std::vector<A> > > vv; 
    vv.emplace(vv.end(), 1, std::vector<A>()); 
} 

如果使用g ++ 4.8.5,5.2.0,5.3.0和-DDDDEQUE編譯我得到C++的std :: deque的拷貝構造函數問題

.../bits/stl_construct.h:75:7: error: use of deleted function ‘A::A(const A&)’ 
    { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } 
    ^
gcc.cpp:11:5: note: declared here 
     A(A const& rhs)   = delete; 

結束了詳細的錯誤信息,而不-D...編譯OK 。 用VC2015,VC2012兩個版本編譯OK。 deque(但不是vector)是否需要gcc的拷貝構造函數?

+2

無關,您在移動賦值運算符中缺少一個「返回」值。而fwiw,即使定義了「DDDEQUE」,也可以將clang 3.8添加到編譯的工具鏈列表中。 – WhozCraig

+0

這似乎更多關於gcc的問題。所以也許'gcc'應該是一個標籤。順便說一句,任何區別,如果你使用'vd.emplace(vd.end(),1,std :: move(std :: deque ()));'而不是? – Walter

回答

3

這似乎是特定於libstdC++(gcc);給出下面的代碼;

struct A 
{ 
    A() {}; 
    A(A&&) noexcept { } 
    A& operator=(A&&) noexcept { return *this; } 
    ~A() { } 
}; 

int main() 
{ 
    std::vector<A> a; 
    a.push_back(A{}); // or emplace(a.end()... etc. 
    std::vector<std::deque<A>> b; 
    b.push_back(std::deque<A>()); 
    std::vector<std::pair<int,A>> c; 
    c.push_back(std::pair<int,A>{}); 
    std::vector<std::pair<int,std::deque<A>>> d; 
    d.push_back(std::pair<int,std::deque<A>>{}); 
} 

G ++編譯失敗b,和d,鐺編譯所有4(除了可能d取決於libc中的版本++使用)和MSVC編譯所有4例(利用自己的相關聯的標準庫;具有的libstdC++,鐺也未通過bd)。

deque(但不是vector)需要gcc的拷貝構造函數嗎?

看起來好像是,gcc仍然需要拷貝構造函數。


更正式地說;在C++ 03 std::deque中要求容器中使用的類型爲可複製的構造可分配的複製。這在C++ 11中發生了變化,需求放寬了,儘管通常仍然需要完整的類型 - 考慮到OP示例,標準庫仍然需要複製構造和分配。

從鏈接的引用;

T - 元素的類型。

T必須滿足CopyAssignable拷貝構造的要求。 (直到C++ 11)

對元素施加的要求取決於對容器執行的實際操作。一般來說,要求元素類型是完整的類型,並且符合Erasable的要求,但是許多成員函數會施加更嚴格的要求。 (自C++ 11以來)

+1

「*這在C++ 11中有所改變,您可以使用語言級別來啓用支持*,移動構造函數,emplace函數,刪除函數,這些都是C++ 11的特性(= OP已經啓用了C++ 11) –

+0

@PiotrSkotnicki。我意識到 - 但他的代碼仍然需要複製構造函數等。 – Niall

+0

vector也有相同的寬鬆要求,我讀到這樣一個問題:「哪種操作會導致deque需要複製構造性」 –