当需要特定类型的向量时,通过引用传递 void 指针的向量

Passing vector of void pointers by reference when a vector of specific type is expected

本文关键字:向量 引用 指针 void 类型      更新时间:2023-10-16

请考虑以下场景:

class A
{
    public:
        int a;
        A(int _a) : a(_a) {}
};
void Get(std::vector<A*>& vec)
{
    A* a1 = new A(5);
    A* a2 = new A(50);
    A* a3 = new A(500);
    vec.push_back(a1);
    vec.push_back(a2);
    vec.push_back(a3);
}
int main()
{
    // Scenario 1
    auto vec = std::vector<A*>();
    Get(vec);
    for(auto* v : vec)
        std::cout << v->a << std::endl;
    // Scenario 2: 
    auto vecvoid = std::vector<void*>();
    vecvoid.assign(vec.begin(), vec.end());
    for(auto* v : vecvoid)
        std::cout << static_cast<A*>(v)->a << std::endl;
    return 0;
}

在场景 2 中,是否可以将vecvoid直接传递给Get()(不重载/修改Get()(,而不是使用如上所示的两步方法(函数调用后跟调用 vector::assign()(?

幸运的是,这是不可能的。
std::vector<A*>std::vector<void*>是不相关的类型。

考虑一下如果可能会发生什么:

void G(std::vector<A*>& vec)
{
    *vec[0] = A(7);
}
// ...
int x = 0;
std::vector<void*> v = { &x };
G(v); // Oops.

它可能适用于具有reinterpret_cast的常见编译器,但它显然调用了未定义的行为,因为它不是reinterpret_cast的有效使用:

Get(reinterpret_cast<std::vector<A*>&>(vecvoid));

我刚刚用CLang 3.4对其进行了测试,它甚至没有警告就给出了预期的结果。这并不奇怪,因为无论指针的类型如何,为将指针推送到向量中而生成的汇编代码都是相同的。但是您必须控制生成的程序集以确保...

TL/DR:请不要那样做!它根本不是C++代码,因为正如您在其他答案中被告知的那样,vector<void *>vector<A *>是完全不同的类型。

在场景 2 中,是否可以将 vecvoid 直接传递给 Get(([?

不,不是。

虽然A*可以转换为void*,但std::vector<A*>std::vector<void*>完全不同。另一种选择是:

struct A {};
A a1, a2;
auto veca = std::vector<A*>{&a1, &a2};
auto vecvoid = std::vector<void*>{begin(veca), end(veca)};