【问题标题】:const vector reference arguments in c++C++ 中的 const 向量引用参数
【发布时间】:2017-07-05 13:12:09
【问题描述】:

我认为自己对 C++ 的更基本方面相当了解,但有时我会感到困惑。我正在尝试实现一对作用于std::vector 实例的函数,并对它们的值进行一些操作,而不是就地更改它们。自然地,我认为通过const& 是合理的做法。但是,下面的MWE编译失败,我想了解一下原因:

#include<vector>

void func1(const std::vector<const char* const>& v){
     // do stuff
}

void func2(const std::vector<const std::vector<const char* const> >& v){
  for(int i=0;i<v.size();++i){
    func1(v[i]);
  }
}

int main(){
    return 0;
}

错误信息看起来有点像这样:

In file included from...include/c++/4.9.3/x86_64-unknown-linux-gnu/bits/c++allocator.h:33:0,
                 from...include/c++/4.9.3/bits/allocator.h:46,
                 from...include/c++/4.9.3/vector:61,
                 from test.cxx:2:
.../ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<const std::vector<const char* const> >’:
.../bits/allocator.h:92:11:   required from ‘class std::allocator<const std::vector<const char* const> >’
.../ext/alloc_traits.h:172:53:   required from ‘struct __gnu_cxx::__alloc_traits<std::allocator<const std::vector<const char* const> > >’
.../bits/stl_vector.h:75:28:   required from ‘struct std::_Vector_base<const std::vector<const char* const>, std::allocator<const std::vector<const char* const> > >’
.../bits/stl_vector.h:214:11:   required from ‘class std::vector<const std::vector<const char* const> >’
test.cxx:9:18:   required from here
.../ext/new_allocator.h:93:7: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = const std::vector<const char* const>; __gnu_cxx::new_allocator<_Tp>::const_pointer = const std::vector<const char* const>*; __gnu_cxx::new_allocator<_Tp>::const_reference = const std::vector<const char* const>&]’ cannot be overloaded
       address(const_reference __x) const _GLIBCXX_NOEXCEPT
       ^
.../ext/new_allocator.h:89:7: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = const std::vector<const char* const>; __gnu_cxx::new_allocator<_Tp>::pointer = const std::vector<const char* const>*; __gnu_cxx::new_allocator<_Tp>::reference = const std::vector<const char* const>&]’
       address(reference __x) const _GLIBCXX_NOEXCEPT
       ^
.../ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<const char* const>’:
.../bits/allocator.h:92:11:   required from ‘class std::allocator<const char* const>’
.../ext/alloc_traits.h:172:53:   required from ‘struct __gnu_cxx::__alloc_traits<std::allocator<const char* const> >’
.../bits/stl_vector.h:75:28:   required from ‘struct std::_Vector_base<const char* const, std::allocator<const char* const> >’
.../bits/stl_vector.h:214:11:   required from ‘class std::vector<const char* const>’
test.cxx:10:14:   required from here
.../ext/new_allocator.h:93:7: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = const char* const; __gnu_cxx::new_allocator<_Tp>::const_pointer = const char* const*; __gnu_cxx::new_allocator<_Tp>::const_reference = const char* const&]’ cannot be overloaded
       address(const_reference __x) const _GLIBCXX_NOEXCEPT
       ^
.../ext/new_allocator.h:89:7: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = const char* const; __gnu_cxx::new_allocator<_Tp>::pointer = const char* const*; __gnu_cxx::new_allocator<_Tp>::reference = const char* const&]’
       address(reference __x) const _GLIBCXX_NOEXCEPT

我对错误消息声称不能重载的事实感到困惑,指的是在func2 中调用func1。解决 const 对向量条目的引用似乎存在问题,但我真的不明白为什么这段代码无法编译。对于此类行为的任何解释、建议或指向文档的指针,我都很高兴。

【问题讨论】:

    标签: c++ vector constants pass-by-reference


    【解决方案1】:
    std::vector<const char* const>
    

    您正在尝试使用const 类型实例化一个向量。该类型至少需要可移动,但事实并非如此。改为:

    std::vector<const char*>
    

    改为

    【讨论】:

    • @nwp:是的,我的意思是可移动分配。
    • 感谢您的建议。不幸的是,这并不能真正解决问题,因为func2 中的错误仍然存​​在。我还需要从func2 标头的内部向量中删除const 才能成功编译。
    • 嗯,是的。我的意思是“无论您在哪里拥有char const * const 的向量,都可以更改它”。
    【解决方案2】:

    如果您事先知道这意味着什么,编译器会正确报告问题。

    std::allocatoraddress 有两个重载。

    address(reference __x)
    address(const_reference __x)
    

    编译器的问题是,对于模板类型const TT&amp;const T&amp; 这两个类型将是相同的类型。然后它认为同一个重载有两个副本。

    【讨论】:

    • 好的,有道理。但是我该如何避免这个问题呢?
    • 啊哈!因此,如果您创建自己的分配器,它只具有一个重载,那么您可以将其用作向量的分配器,并且一切都会顺利运行!
    • @carsten :只需在向量中使用非常量类型:char const * 而不是char const * const
    • 看来我也得把这个const std::vector&lt;const std::vector&lt;const char*&gt; &gt;&amp;改成这个const std::vector&lt;std::vector&lt;const char*&gt; &gt;&amp;
    猜你喜欢
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    相关资源
    最近更新 更多