【问题标题】:Why can I not call reserve on a vector of const elements? [duplicate]为什么我不能在 const 元素的向量上调用 reserve? [复制]
【发布时间】:2013-09-06 07:27:03
【问题描述】:

有人告诉我,在插入大量元素之前调用vector.reserve() 是一种很好的做法。我刚遇到一种情况,我想将大量 const 元素放入 vector 中。但是,当调用reserve() 时,会引发编译器错误。

考虑以下重现问题的代码:

#include <vector>

int main()
{
    std::vector<const int> vec;
    vec.reserve(2);
}

这会导致以下巨大的编译器错误:

在 /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++allocator.h:33:0 包含的文件中,
                 来自 /usr/include/c++/4.8/bits/allocator.h:46,
                 来自 /usr/include/c++/4.8/vector:61,
                 来自vecreserve.cpp:1:
/usr/include/c++/4.8/ext/new_allocator.h:在“struct __gnu_cxx::new_allocator”的实例化中:
/usr/include/c++/4.8/bits/allocator.h:92:11:来自‘class std::allocator’所需
/usr/include/c++/4.8/bits/alloc_traits.h:90:43: 来自‘struct std::allocator_traits >’
/usr/include/c++/4.8/ext/alloc_traits.h:121:10: 来自‘struct __gnu_cxx::__alloc_traits >’
/usr/include/c++/4.8/bits/stl_vector.h:75:28: 来自‘struct std::_Vector_base >’
/usr/include/c++/4.8/bits/stl_vector.h:210:11:从‘class std::vector’需要
vecreserve.cpp:5:26: 从这里需要
/usr/include/c++/4.8/ext/new_allocator.h:93:7: 错误:'const _Tp* __gnu_cxx::new_allocator::address(__gnu_cxx::new_allocator::const_reference) const [with _Tp = const int; __gnu_cxx::new_allocator::const_pointer = const int*; __gnu_cxx::new_allocator::const_reference = const int&]' 不能被重载
       地址(const_reference __x) const _GLIBCXX_NOEXCEPT
       ^
/usr/include/c++/4.8/ext/new_allocator.h:89:7: error: with ‘_Tp* __gnu_cxx::new_allocator::address(__gnu_cxx::new_allocator::reference) const [with _Tp = const int; __gnu_cxx::new_allocator::pointer = const int*; __gnu_cxx::new_allocator::reference = const int&]’
       地址(参考 __x) const _GLIBCXX_NOEXCEPT
       ^
/usr/include/c++/4.8/ext/new_allocator.h:在 'void __gnu_cxx::new_allocator::deallocate(__gnu_cxx::new_allocator::pointer, __gnu_cxx::new_allocator::size_type) 的实例化中 [with _Tp = const int ; __gnu_cxx::new_allocator::pointer = const int*; __gnu_cxx::new_allocator::size_type = long unsigned int]’:
/usr/include/c++/4.8/bits/stl_vector.h:174:4: 需要来自 'void std::_Vector_base::_M_deallocate(std::_Vector_base::pointer, std::size_t) [with _Tp = const int ; _Alloc = std::allocator; std::_Vector_base::pointer = const int*; std::size_t = long unsigned int]’
/usr/include/c++/4.8/bits/vector.tcc:80:28: 需要来自'void std::vector::reserve(std::vector::size_type) [with _Tp = const int; _Alloc = std::allocator; std::vector::size_type = long unsigned int]’
vecreserve.cpp:6:16: 从这里需要
/usr/include/c++/4.8/ext/new_allocator.h:110:30:错误:从‘const void*’到‘void*’的无效转换[-fpermissive]
       { ::运算符删除(__p); }
                              ^
在 /usr/include/c++/4.8/ext/new_allocator.h:33:0 包含的文件中,
                 来自 /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++allocator.h:33,
                 来自 /usr/include/c++/4.8/bits/allocator.h:46,
                 来自 /usr/include/c++/4.8/vector:61,
                 来自vecreserve.cpp:1:
/usr/include/c++/4.8/new:95:6: 错误:初始化‘void operator delete(void*)’的参数 1 [-fpermissive]
 无效运算符删除(无效*)_GLIBCXX_USE_NOEXCEPT
      ^
在 /usr/include/c++/4.8/vector:60:0 包含的文件中,
                 来自vecreserve.cpp:1:
/usr/include/c++/4.8/bits/stl_algobase.h:在'_OI std::__copy_move_a(_II, _II, _OI) 的实例化中 [with bool _IsMove = true; _II = 常量 int*; _OI = const int*]':
/usr/include/c++/4.8/bits/stl_algobase.h:428:38: 需要从'_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = true; _II = 常量 int*; _OI = const int*]’
/usr/include/c++/4.8/bits/stl_algobase.h:460:17: 需要从'_OI std::copy(_II, _II, _OI) [with _II = std::move_iterator; _OI = const int*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:93:53: 来自'static _ForwardIterator std::__uninitialized_copy::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = const int*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:117:41: 来自‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = const int*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63: 来自‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator&) [with _InputIterator = std::move_iterator; _ForwardIterator = 常量 int*; _Tp = const int]’
/usr/include/c++/4.8/bits/stl_vector.h:1142:29: 来自 'std::vector::pointer std::vector::_M_allocate_and_copy(std::vector::size_type, _ForwardIterator, _ForwardIterator) [与 _ForwardIterator = std::move_iterator; _Tp = 常量 int; _Alloc = std::allocator; std::vector::pointer = const int*; std::vector::size_type = long unsigned int]’
/usr/include/c++/4.8/bits/vector.tcc:75:70: 需要来自'void std::vector::reserve(std::vector::size_type) [with _Tp = const int; _Alloc = std::allocator; std::vector::size_type = long unsigned int]’
vecreserve.cpp:6:16: 从这里需要
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: 错误:没有匹配函数调用'std::__copy_move::__copy_m(const int*&, const int*&, const int*& )'
                        _Category>::__copy_m(__first, __last, __result);
                                                                      ^
/usr/include/c++/4.8/bits/stl_algobase.h:390:70:注意:候选人是:
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: 注意:模板静态 _Tp* std::__copy_move::__copy_m(const _Tp*, const _Tp*, _Tp*) [with _Tp = _Tp; bool _IsMove = true]
         __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
         ^
/usr/include/c++/4.8/bits/stl_algobase.h:368:9:注意:模板参数推导/替换失败:
/usr/include/c++/4.8/bits/stl_algobase.h:390:70:注意:推断参数“_Tp”(“int”和“const int”)的冲突类型
                        _Category>::__copy_m(__first, __last, __result);
                                                                      ^

为什么会这样?我不应该在vectorconst 元素上调用reserve 吗?如果是,为什么不呢?

【问题讨论】:

  • 因为你的const int
  • @P0W 我知道,你能说得更具体点吗?为什么我不能在 const intvector 上调用 reserve
  • 因为当您调用 reserve() 时,它会为它们分配空间,但是您以后将无法修改它们(因为它们是 const ......)所以它们会 始终具有由 reserve() 分配的默认值。也就是说,对于这个非常特殊的问题,我会抛弃 const(因为它只会影响编译器检查,而不影响生成的代码)。

标签: c++ vector


【解决方案1】:

对于vector 类声明的元素,您违反了requirements。元素必须是CopyAssignable

【讨论】:

  • 技术上,vector 的许多成员函数要求元素是 CopyAssignable/CopyConstructableMoveAssignable/MoveConstructable。
  • 另外:它表明 'std::vector vec;'不实例化函数。
  • 这在 c++17 中发生了变化,容器现在可以识别分配器,元素类型要求现在改为 Erasable。换句话说,它必须能够调用std::allocator_traits&lt;A&gt;::destroy(m, p);
【解决方案2】:

const int 不是放入任何标准容器的有效类型,因为它不可分配。

【讨论】:

    猜你喜欢
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多