为什么在C++中void*是坏的?有哪些替代方案?

我正在做一个项目来实现这个 Multi-Join algorithm。我想到的代码看起来像这样:

template <typename A, typename B, typename C>
vector<tuple<A,B,C>> multi_join(vector<pair<A,B>> R1, vector<pair<B,C>> R2, vector<pair<A,C>> R3)
{
    void* existing = new vector<tuple<>>;
    void* p1, p2, p3;
    
    p1 = &propose<A>(R1, *(vector<tuple<>>*) existing); // Returns vector<tuple<A>>
    p2 = &propose<A>(R2, *(vector<tuple<>>*) existing);
    p3 = &propose<A>(R3, *(vector<tuple<>>*) existing);

    existing = &intersect(*(vector<tuple<A>>*) p1, *(vector<tuple<A>>*) p2, *(vector<tuple<A>>*) p3);
    
    p1 = &propose<B>(R1, *(vector<tuple<A>>*) existing); // Returns vector<tuple<A, B>>
    p2 = &propose<B>(R2, *(vector<tuple<A>>*) existing);
    p3 = &propose<B>(R3, *(vector<tuple<A>>*) existing);

    existing = &intersect(*(vector<tuple<A, B>>*) p1, *(vector<tuple<A, B>>*) p2, *(vector<tuple<A, B>>*) p3);

    p1 = &propose<C>(R1, *(vector<tuple<A, B>>*) existing); // Returns vector<tuple<A, B, C>>
    p2 = &propose<C>(R2, *(vector<tuple<A, B>>*) existing);
    p3 = &propose<C>(R3, *(vector<tuple<A, B>>*) existing);

    existing = &intersect(*(vector<tuple<A, B, C>>*) p1, *(vector<tuple<A, B, C>>*) p2, *(vector<tuple<A, B, C>>*) p3);

    return *(vector<tuple<A, B, C>>*) existing;
}

请注意existing必须如何从 typevector<tuple<>>vector<tuple<A>>tovector<tuple<A, B>>和 finally 到vector<tuple<A, B, C>>。这是一个有限的例子,但我们的想法是最终实现它,以便可以有任意数量的输入向量。

我已经研究了如何尝试做到这一点,这void*似乎是最简单的方法,但我也遇到过消息人士说这是糟糕的代码。

我有什么选择?有没有其他方法可以做到这一点?

回答

在代码中的任何和所有行中,类型existing都是已知且固定的。

auto va1 = propose<A>(R1, std::vector<std::tuple<>>{}); // Returns vector<tuple<A>>
auto va2 = propose<A>(R2, std::vector<std::tuple<>>{});
auto va3 = propose<A>(R3, std::vector<std::tuple<>>{});

auto AIntersect = intersect(va1, va2, va3);

auto vab1 = propose<B>(R1, AIntersect); // Returns vector<tuple<A, B>>
auto vab2 = propose<B>(R2, AIntersect); // Returns vector<tuple<A, B>>
auto vab3 = propose<B>(R3, AIntersect); // Returns vector<tuple<A, B>>

auto ABIntersect = intersect(vab1, vab2, vab3);

auto vabc1 = propose<c>(R1, ABIntersect); // Returns vector<tuple<A, B, C>>
auto vabc2 = propose<c>(R2, ABIntersect); // Returns vector<tuple<A, B, C>>
auto vabc3 = propose<C>(R3, ABIntersect); // Returns vector<tuple<A, B, C>>

auto ABCIntersect = intersect(vabc1, vabc2, vabc3);
return ABCIntersect;

这不再需要指向函数返回值的指针 (ick),并为所有内容提供正确的类型名称。它也更短。

顺便new std::vector一句,如果你曾经这样做过,你的代码有 99.9% 的机会被错误地设计。 std::vector管理上堆数据,把它放在堆的缓冲区几乎总是你搞砸了而盲目更换标志new int[100]new std::vector<int>

您的代码调用了new并且从未调用过delete;它泄漏了。

你把代码的返回值的地址intersectpropose。谁拥有那段记忆?我没有线索; 它可能是悬空的,你的代码做了 UB。

所以我将其更改为auto并存储std::vector以干净地管理堆分配的返回值。


以上是为什么在C++中void*是坏的?有哪些替代方案?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>