gpt4 book ai didi

c++ - 在 C++ 的嵌入式环境中使用继承的 "price"是什么?

转载 作者:太空狗 更新时间:2023-10-29 20:00:26 25 4
gpt4 key购买 nike

我正在使用 C++ 开始一个新的嵌入式项目,我想知道使用面向接口(interface)的设计是否过于昂贵。像这样:

typedef int data;

class data_provider {

public:
virtual data get_data() = 0;
};

class specific_data_provider : public data_provider {
public:
data get_data() {
return 7;
}
};

class my_device {
public:
data_provider * dp;
data d;

my_device (data_provider * adp) {
dp = adp;
d = 0;
}

void update() {
d = dp->get_data();
}
};

int
main() {
specific_data_provider sdp;
my_device dev(&sdp);

dev.update();

printf("d = %d\n", dev.d);

return 0;
}

最佳答案

继承本身是免费的。例如,从性能/内存的角度来看,BC 是相同的:

struct A { int x; };
struct B : A { int y; };
struct C { int x, y; };

仅当您拥有虚函数时,继承才会产生成本。

struct A { virtual ~A(); };
struct B : A { ... };

在这里,在几乎所有的实现中,AB 都将由于虚函数的存在而增大一个指针大小。

虚函数也有其他缺点(与非虚函数相比)

  1. 虚函数要求您在调用时查找虚表。如果该 vtable 不在缓存中,那么您将遇到 L2 未命中,这在嵌入式平台上可能会非常昂贵(例如,在当前的游戏机上超过 600 个周期)。
  2. 即使您命中了 L2 缓存,如果您分支到许多不同的实现,那么您可能会在大多数调用中遇到分支预测错误,从而导致管道刷新,这又会花费很多周期。
  3. 由于虚函数基本上不可能内联(极少数情况除外),您还会错失许多优化机会。如果您调用的函数很小,那么与内联非虚函数相比,这可能会严重影响性能。
  4. 虚拟调用会导致代码膨胀。每个虚函数调用都会添加几个字节的指令来查找 vtable,并为 vtable 本身添加许多字节。

如果你使用多重继承,那么事情会变得更糟。

通常人们会告诉您“在分析器告诉您之前不要担心性能”,但如果性能对您来说非常重要,那么这是一个糟糕的建议。如果您不担心性能,那么最终会发生到处都是虚函数,并且当您运行探查器时,没有一个热点需要优化——整个代码库都需要优化。

如果性能对您很重要,我的建议是进行设计。设计时尽可能避免使用虚函数。围绕缓存设计数据:优先使用数组而不是基于节点的数据结构,例如 std::liststd::map。即使你有一个包含几千个元素并经常插入中间的容器,我仍然会在某些架构上选择数组。为插入复制数据而丢失的数千个周期很可能会被每次遍历时获得的缓存局部性所抵消(还记得单个 L2 缓存未命中的成本吗?您可以期待很多这样的情况遍历链表时)

关于c++ - 在 C++ 的嵌入式环境中使用继承的 "price"是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7002004/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com