【问题标题】:reference and pointer typecasting in C++C++ 中的引用和指针类型转换
【发布时间】:2018-09-25 12:13:36
【问题描述】:

我能够将vector&lt;void*&gt; 的引用类型转换为vector&lt;Foo*&gt; 的引用,而我无法对vector&lt;void*&gt; to vector&lt;Foo*&gt; 进行类型转换。我收到错误 C2440: 'reinterpret_cast' : cannot convert from 'std::vector<_ty>' to 'std::vector<_ty>' 为什么?

而且我能够将 void* 类型转换为 Foo* 而不会出现编译器错误。

void* g =&foo;
reportFooVector2(reinterpret_cast<Foo*>(g));

下面是我的全部代码。

#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;

struct Foo
{
  string s;
  int i;
};


void reportFooVector( vector <Foo*> * pvf )
{

}


void reportFooVector1( vector <Foo*> pvf )
{
}

void reportFooVector2( Foo *pvf )
{
}


int main()
{
    struct Foo foo = {"foo",  5};
    struct Foo goo = {"goo", 10};
    void* g =&foo;
    reportFooVector2(reinterpret_cast<Foo*>(g));
    vector <void *> vf;
    vf.push_back(&foo);
    vf.push_back(&goo);
    reportFooVector1( reinterpret_cast< vector < Foo * >  >(vf));
    reportFooVector( reinterpret_cast< vector < Foo * > * >(&vf));
}

在上述程序中,我得到编译器 error C2440: 'reinterpret_cast' : cannot convert from 'std::vector<_ty>' to 'std::vector<_ty>' when调用行reportFooVector1( reinterpret_cast&lt; vector &lt; Foo * &gt; &gt;(vf));

请问有人能说出原因吗?

【问题讨论】:

  • void* 是一个例外,它表示允许与任何其他指针类型进行转换。 std::vector&lt;void*&gt;没有这样的例外
  • 原因是在 C++ 中是不允许的。一个左值表达式只能被重新转换为一个类型的reference,除非左值表达式是一个指针、一个整数和枚举等...... vector 两者都不是,唯一可以 reinterpret_casted 的就是一个引用。
  • 那些是指针,而不是引用。不是挑剔,因为 C++ 有实际的引用,而且这些是与指针不同的类型。最好使术语正确以避免混淆。
  • @SamVarshavchik 对我来说似乎是一个完美的答案,为什么要在评论中发布它?
  • 为什么要存储一个 void* 指针向量?

标签: c++ stl


【解决方案1】:

首先,reinterpret_cast 做了什么?

  • 将任何指针类型转换为任何其他指针类型,甚至是不相关的类
  • 将指针转换为整数类型或从整数类型转换

请注意,这里所做的一切都涉及在指针类型之间进行转换,或者从指针类型转换。所以重要的是要注意reinterpret_cast&lt;vector&lt;Foo*&gt;&gt;(vf) 无效,因为它将vector&lt;void*&gt; 转换为vector&lt;Foo*&gt;。尽管这些都是vectors,包含指针,但vfvector&lt;Foo*&gt;本身都不是指针。

解决了这个问题后,让我们讨论reinterpret_cast&lt;vector&lt;Foo*&gt;*&gt;(&amp;vf) 这是如果由于Type Aliasing 上的规则而被取消引用,将导致未定义的行为。
假设reinterpret_cast 的输入是DynamicType,输出是AliasedType,那么reinterpret_cast 只有在以下情况下才有效:

  • AliasedType 和 DynamicType 类似
  • AliasedType 是 DynamicType 的(可能是 cv 限定的)有符号或无符号变体
  • AliasedType 是 std::bytecharunsigned char:这允许将任何对象的对象表示形式检查为字节数组

非正式地,如果忽略顶级 cv-qualification,两种类型是相似的:

  • 它们是同一类型
  • 都是指针,指向的类型类似
  • 都是指向同一个类的成员的指针,所指向的成员的类型相似
  • 它们都是相同大小的数组或都是未知边界的数组,并且数组元素类型相似

由于对于 vector&lt;void*&gt;*vector&lt;Foo*&gt;* 而言,这些都不正确,因此取消引用此 reinterpret_cast 的输出是未定义的行为。


现在我们已经讨论了为什么这些都是不可取的;让我建议你改为:void reportFooVector(void** pvf, const size_t count) 你可以通过这样做来调用它:reportFooVector(data(vf), size(vf)) 在内部到 reportFooVector 你需要将单个元素转换为 Foo*s 以便对它们进行操作。

【讨论】:

    猜你喜欢
    • 2020-11-17
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    相关资源
    最近更新 更多