为什么指针向量不能转换为const指针的const向量? [英] Why is a vector of pointers not castable to a const vector of const pointers?

查看:99
本文介绍了为什么指针向量不能转换为const指针的const向量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类型 vector< char *> 不能转换为 const vector< const char *> 。例如,以下给出了编译错误:

The type vector<char *> is not convertible to const vector<const char*>. For example, the following gives a compilation error:

#include <vector>

using namespace std;

void fn(const vector<const char*> cvcc)
{
}

int main()
{
    vector<char *> vc = vector<char *>(); 

    fn(vc);
}

我理解为什么 vector< char *> 不能转换为 vector< const char *> -类型为 const char * 可以添加到向量中,然后它们可以作为非常量访问。但是,如果向量本身是const,则不会发生这种情况。

I understand why vector<char*> is not convertable to vector<const char*> - extra members of type const char * may be added to the vector, and afterwards they would be accessible as non-const. However, if the vector itself is const, this can't happen.

我的最佳猜测是,这将是无害的,但不允许编译器执行推断这将是无害的。

My best guess is that this would be harmless, but there is no way the compiler is allowed to deduce that this would be harmless.

如何解决?

这个问题是由C ++ FQA 此处

This question was suggested by the C++ FQA here.

推荐答案

void fn(const vector<const char*>)

因为函数类型的顶级 const 限定符已删除,所以它是(在调用站点)等效于:

As the top-level const qualifier is dropped for the function type, this is (at the call site) equivalent to:

void fn(vector<const char*>)

由于标准库容器遵循值语义,两者都要求传递的向量的副本

Both of which request a copy of the passed vector, because Standard Library containers follow value semantics.

您可以:


  • 通过 fn({vc.begin( ),vc.end()}),要求隐式转换

  • 将签名更改为例如 void fn(vector< const char *> const&),即获取引用

  • call it via fn({vc.begin(), vc.end()}), requesting an explicit conversion
  • change the signature to, e.g. void fn(vector<const char*> const&), i.e. taking a reference

如果您可以修改 fn 的签名,则可以遵循 GManNickG 建议并使用迭代器 /一个范围:

If you can modify the signature of fn, you can follow GManNickG's advice and use iterators / a range instead:

#include <iostream>
template<typename ConstRaIt>
void fn(ConstRaIt begin, ConstRaIt end)
{
    for(; begin != end; ++begin)
    {
        std::cout << *begin << std::endl;
    }
}

#include <vector>
int main()
{
    char arr[] = "hello world";
    std::vector<char *> vc;
    for(char& c : arr) vc.push_back(&c);

    fn(begin(vc), end(vc));
}

这给出了漂亮的输出结果

This gives the beautiful output


hello world
ello world
llo world
lo world
o world
 world
world
orld
rld
ld
d






基本问题是围绕标准库容器。如果您只需要不断访问数据,则无需知道实际的容器类型,而可以使用模板。这消除了 fn 与调用者使用的容器类型之间的耦合。


The fundamental issue is to pass around Standard Library containers. If you only need constant access to the data, you don't need to know the actual container type and can use the template instead. This removes the coupling of fn to the type of container the caller uses.

您已经注意到,这是一个允许通过 std :: vector< const T *& <来访问 std :: vector< T *> 的坏主意/ code>。但是,如果不需要修改容器,则可以使用范围。

As you have noticed, it's a bad idea to allow access of a std::vector<T*> through a std::vector<const T*>&. But if you don't need to modify the container, you can use a range instead.

如果函数 fn 不能或不能是模板,您仍然可以绕过 const char * 的范围,而不是 const char 。这适用于任何保证连续存储的容器,例如原始数组, std :: array s, std :: vector std :: string s。

If the function fn shall not or cannot be a template, you could still pass around ranges of const char* instead of vectors of const char. This will work with any container that guarantees contiguous storage, such as raw arrays, std::arrays, std::vectors and std::strings.

这篇关于为什么指针向量不能转换为const指针的const向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆