【问题标题】:Odd std::vector::emplace() compilation error奇怪的 std::vector::emplace() 编译错误
【发布时间】:2017-05-04 12:12:50
【问题描述】:

我在使用std::vector::emplace()std::vector::emplace_back() 时遇到了一个奇怪的编译器错误:

#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,则代码编译得很好。这是怎么回事?

【问题讨论】:

    标签: c++ c++11 vector compiler-errors emplace


    【解决方案1】:

    你的问题不在于vec.emplace_back(1);。由于std::vector&lt;Foo&gt; vec(10);,您收到编译错误。该行试图创建一个具有 10 个默认构造元素的向量。由于您的类没有默认构造函数,因此您无法创建 10 个默认元素。

    要让它工作,你需要提供一个类的实例,它可以复制到向量中。看起来像

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

    或者你可以只添加一个默认构造函数。


    std::vector&lt;Foo&gt; vec{}; 不会给您带来任何问题,因为它不会尝试默认构造任何元素。空构造函数返回一个大小为 0 的向量,这意味着没有构造任何对象,从而避免了未定义的默认构造函数。

    【讨论】:

      【解决方案2】:

      原因是std::vector&lt;Foo&gt; vec(10) 将实例化一个带有 10 个“空”Foo 对象的向量,即需要调用默认构造函数的类 Foo 的实例。但是,您的类 Foo 不提供默认构造函数。

      第二条语句std::vector&lt;Foo&gt; vec{} 实例化了一个空向量,因此没有实例化Foo-object(这将需要一个默认构造函数)。

      要解决您的问题,请在Foo 中定义一个默认构造函数:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-01-04
        • 2022-12-07
        • 2011-03-06
        • 1970-01-01
        • 2011-01-22
        • 2016-01-23
        相关资源
        最近更新 更多