相关疑难解决方法(0)

最终用于C++中的优化?

class A {
public:
    virtual void f() = 0;
};

class B : public A {
public:
    void f() final override { };
};

int main() {
    B* b = new B();
    b->f();
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,编译器是否仍需要执行v表查找b->f();,或者是否可以B::f()直接调用,因为它已被标记final

c++ virtual final c++11

39
推荐指数
1
解决办法
5833
查看次数

`std :: variant` vs.继承vs.其他方式(性能)

我想知道std::variant性能。什么时候不应该使用它?似乎虚拟函数仍然比使用虚拟函数好得多,std::visit这让我感到惊讶!

pattern checking解释std::holds_alternativesoverloaded方法之后,Bjarne Stroustrup在“ C ++之旅”中谈到了这一点:

这基本上等效于虚拟函数调用,但可能更快。与所有性能要求一样,当性能至关重要时,应通过测量来验证“可能更快”。对于大多数用途,性能差异不明显。

我已经确定了一些想到的方法,这些是结果:

基准 http://quick-bench.com/N35RRw_IFO74ZihFbtMu4BIKCJg

如果启用优化,您将得到不同的结果:

启用op的基准

http://quick-bench.com/p6KIUtRxZdHJeiFiGI8gjbOumoc

这是我用于基准测试的代码;我确信,有更好的方法来实现和使用变体来代替虚拟关键字来使用它们(继承与std :: variant):

删除旧代码;看看更新

任何人都可以解释一下实现此用例的最佳方法是什么,这std::variant使我不得不进行测试和基准测试:

我当前正在实现RFC 3986,它是“ URI”,在我的用例中,该类将更多地用作const,并且可能不会做很多更改,并且用户更有可能使用此类来查找每个特定类URI的一部分,而不是生成URI;因此,有意义的是使用std::string_viewURI的每个段,而不是将其分开std::string。问题是我需要为其实现两个类。当我只需要一个const版本时;另一个用于当用户想要创建URI而不是提供一个URI并进行搜索时。

所以我用a template来解决有其自身问题的内容;但是后来我意识到我可以使用std::variant<std::string, std::string_view>(或者也许std::variant<CustomStructHoldingAllThePieces, std::string_view>);所以我开始研究以查看是否确实有助于使用变体。从这些结果看,似乎要使用继承,virtual如果我不想实现两个不同的const_uriand uri类,那是我最好的选择。

您认为我该怎么办?


更新(2)

感谢@gan_在我的基准代码中提到并解决了起吊问题。 基准 http://quick-bench.com/Mcclomh03nu8nDCgT3T302xKnXY

我对try-catch hell的结果感到惊讶,但是由于有了现在有意义的注释

更新(3)

我删除了该try-catch方法,因为它确实很糟糕。而且还随机更改了所选值,并且通过它的外观,我看到了更现实的基准。virtual毕竟这似乎不是正确的答案。 随机访问 http://quick-bench.com/o92Yrt0tmqTdcvufmIpu_fIfHt0

http://quick-bench.com/FFbe3bsIpdFsmgKfm94xGNFKVKs(无内存泄漏大声笑)

更新(4)

我消除了生成随机数的开销(我在上一次更新中已经做到了,但是似乎我抓取了错误的URL作为基准),并添加了EmptyRandom来理解生成随机数的基准。并且对Virtual进行了一些小的更改,但我认为它没有任何影响。 空随机添加 http://quick-bench.com/EmhM-S-xoA0LABYK6yrMyBb8UeI

http://quick-bench.com/5hBZprSRIRGuDaBZ_wj0cOwnNhw(已删除了“虚拟”,因此您可以更好地比较其余虚拟)


更新(5)

正如豪尔赫·贝隆(Jorge Bellon)在评论中说的 …

c++ performance inheritance c++17 std-variant

35
推荐指数
2
解决办法
1167
查看次数

LTO,虚拟化和虚拟表

比较C++中的虚函数和C中的虚拟表,一般编译器(以及足够大的项目)在虚拟化方面做得很好吗?

天真地看来,C++中的虚函数似乎有更多的语义,因此可能更容易虚拟化.

更新: Mooing Duck提到了内联的虚拟化功能.快速检查显示虚拟表的错过优化:

struct vtab {
    int (*f)();
};

struct obj {
    struct vtab *vtab;
    int data;
};

int f()
{
    return 5;
}

int main()
{
    struct vtab vtab = {f};
    struct obj obj = {&vtab, 10};

    printf("%d\n", obj.vtab->f());
}
Run Code Online (Sandbox Code Playgroud)

我的GCC不会内联f,虽然它是直接调用的,即,虚拟化.C++中的等价物,

class A
{
public:
    virtual int f() = 0;
};

class B
{
public:
    int f() {return 5;}
};

int main()
{
    B b;
    printf("%d\n", b.f());
}
Run Code Online (Sandbox Code Playgroud)

甚至内联f.所以C和C++之间存在第一个区别,尽管我不认为C++版本中添加的语义在这种情况下是相关的.

更新2:为了在C中进行虚拟化,编译器必须证明虚拟表中的函数指针具有特定值.为了在C++中进行虚拟化,编译器必须证明该对象是特定类的实例.在第一种情况下,证据似乎更难.但是,虚拟表通常仅在极少数地方进行修改,最重要的是:仅仅因为它看起来更难,并不意味着编译器不是那么好(否则你可能会认为xoring通常比添加两个更快)整数).

c c++ compiler-optimization

15
推荐指数
2
解决办法
5050
查看次数