ссылка и указатель типов в C ++ - PullRequest
0 голосов
/ 25 сентября 2018

Я могу перевести ссылку vector<void*> на ссылку vector<Foo*>, а я не могу vector<void*> to vector<Foo*>.Я получаю сообщение об ошибке C2440: 'reinterpret_cast': невозможно преобразовать из 'std :: vector <_Ty>' в '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));
}

В приведенной выше программе я получаю компилятор ошибка C2440: 'reinterpret_cast':не может преобразовать из 'std :: vector <_Ty>' в 'std :: vector <_Ty>' при вызове строки reportFooVector1( reinterpret_cast< vector < Foo * > >(vf));

Не могли бы вы рассказать кому-нибудь причину этого?

1 Ответ

0 голосов
/ 25 сентября 2018

Сначала на высоком уровне, что делает reinterpret_cast?

  • Преобразует любой тип указателя в любой другой тип указателя, даже из не связанных классов
  • Приведение указателей к целочисленным типам или из них

Обратите внимание, что все, что здесь делается, включает приведение типов к указателям или к ним.Поэтому важно отметить, что reinterpret_cast<vector<Foo*>>(vf) недопустимо, так как оно преобразует vector<void*> в vector<Foo*>.Несмотря на то, что это vector s, которые содержат указатели, ни vf, ни vector<Foo*> сами по себе не являются указателями.

Обсудив это, давайте обсудим reinterpret_cast<vector<Foo*>*>(&vf) это также приведет к неопределенному поведению, если его разыменовать из-за правил Тип псевдонима .
Учитывая, что входные данные для reinterpret_cast - это DynamicType, а выходные данные - AliasedType, reinterpret_castдопустимо только в том случае, если:

  • AliasedType и DynamicType похожи
  • AliasedType является (возможно, cv-квалифицированным) подписанным или неподписанным вариантом DynamicType
  • AliasedTypeis std::byte, char или unsigned char: это разрешает проверку представления объекта любого объекта в виде массива байтов

Неформально два типа похожи, если, игнорируя верхний уровеньcv-qualification:

  • Они имеют одинаковый тип
  • Они оба указатели, а указываемые типы похожи
  • Они оба указатели на члентого же класса, и тТипы элементов, на которые указывает указатель, аналогичны
  • Они оба являются массивами одинакового размера или массивами с неизвестной границей, а типы элементов массива аналогичны

Так какничего из этого не верно в отношении vector<void*>* и vector<Foo*>* разыменования выходных данных этого reinterpret_cast - неопределенное поведение.


Теперь, когда мы обсудили, почему они оба нежелательны;позвольте мне предложить вам вместо этого: void reportFooVector(void** pvf, const size_t count) Вы можете вызвать это, выполнив: reportFooVector(data(vf), size(vf)) Внутри reportFooVector вам нужно привести отдельные элементы к Foo* с, чтобы работать с ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...