2017-05-04 47 views
2

我遇到一個奇怪的編譯器錯誤,而使用std::vector::emplace()std::vector::emplace_back()奇的std ::矢量::佈設()編譯錯誤

#include <vector> 

struct Foo { 
    int bar; 

    Foo(int _bar) : bar(_bar) { } 
}; 

int main() { 
    // Declaration 1 
    std::vector<Foo> vec(10); 

    // Declaration 2 
    // std::vector<Foo> vec{}; 

    vec.emplace_back(1); 

    return 0; 
} 

當我compile,我得到了以下錯誤:

In file included from /usr/include/c++/6/vector:62:0, 
       from prog.cpp:2: 
/usr/include/c++/6/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Foo; _Args = {}]’: 
/usr/include/c++/6/bits/stl_uninitialized.h:519:18: required from ‘static _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Foo*; _Size = long unsigned int; bool _TrivialValueType = false]’ 
/usr/include/c++/6/bits/stl_uninitialized.h:575:20: required from ‘_ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Foo*; _Size = long unsigned int]’ 
/usr/include/c++/6/bits/stl_uninitialized.h:637:44: required from ‘_ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, std::allocator<_Tp>&) [with _ForwardIterator = Foo*; _Size = long unsigned int; _Tp = Foo]’ 
/usr/include/c++/6/bits/stl_vector.h:1309:36: required from ‘void std::vector<_Tp, _Alloc>::_M_default_initialize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’ 
/usr/include/c++/6/bits/stl_vector.h:281:30: required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<Foo>]’ 
prog.cpp:11:25: required from here 
/usr/include/c++/6/bits/stl_construct.h:75:7: error: no matching function for call to ‘Foo::Foo()’ 
    { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } 
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
prog.cpp:7:2: note: candidate: Foo::Foo(int) 
    Foo(int _bar) : bar(_bar) { } 
    ^~~ 
prog.cpp:7:2: note: candidate expects 1 argument, 0 provided 
prog.cpp:4:8: note: candidate: constexpr Foo::Foo(const Foo&) 
struct Foo { 
     ^~~ 
prog.cpp:4:8: note: candidate expects 1 argument, 0 provided 
prog.cpp:4:8: note: candidate: constexpr Foo::Foo(Foo&&) 
prog.cpp:4:8: note: candidate expects 1 argument, 0 provided 

但是,如果我註釋掉聲明1並使用聲明2代替,代碼編譯罰款。這裏發生了什麼?

回答

7

您的問題不在vec.emplace_back(1);。由於std::vector<Foo> vec(10);,您收到編譯錯誤。該行試圖創建一個具有10個默認構造元素的向量。由於您的類沒有默認構造函數,因此您無法創建10個默認元素。

爲了讓它正常工作,您需要提供它可以複製到向量中的類的實例。這看起來像

std::vector<Foo> vec(10, Foo(whatever_number_you_want)); 

或者你可以只添加一個默認的構造函數。


std::vector<Foo> vec{};不給你任何問題,因爲它不會嘗試默認構造的任何元素。空構造函數返回一個大小爲0的向量,這意味着沒有構造對象,從而避免了未定義的默認構造函數。

2

原因是std::vector<Foo> vec(10)將實例化一個具有10個「空」Foo對象的向量,即類Foo的實例需要調用默認構造函數。但是,您的類Foo不提供默認構造函數。

第二條語句std::vector<Foo> vec{}實例化一個空向量,因此沒有Foo對象被實例化(這將需要默認的構造函數)。

解決您的問題,定義Foo默認構造函數:

struct Foo { 
    int bar; 

    Foo() : bar(0) {}; 
    Foo(int _bar) : bar(_bar) { }; 
};