C++对象模型之C++额外成本

news/2025/2/25 7:30:55

1.介绍

        C++与C最大的区别,无疑在于面向对象,面向对象编程给C++带来了强大的特性和灵活性。但同时也带来了一定的运行时和编译时的开销。下面介绍C++对象模型的额外成本及其来源。

2.C++的额外成本

        (1)虚函数和动态多态的成本

        虚函数表(vtable):如果一个类包含虚函数,编译器会给该类生成一个虚函数表,每个对象会包含一个指向虚函数表的指针(vptr),这会增加对象的内存开销。(一个指针额外占用8字节)

        虚函数调用开销:调用虚函数时,需要通过 vptr 查找 vtable,再通过 vtable 找到具体的函数地址。这种间接调用比普通函数调用更慢。

        动态绑定:虚函数支持运行时多态,但这也意味着编译器无法在编译时确定具体调用哪个函数,增加了运行时的开销。

class Base {
public:
    virtual void foo() { std::cout << "Base::foo()" << std::endl; }
};

class Derived : public Base {
public:
    void foo() override { std::cout << "Derived::foo()" << std::endl; }
};

int main() {
    Base* obj = new Derived();
    obj->foo();  // 虚函数调用,需要查找 vtable //调用的是派生类的函数
    delete obj;
    return 0;
}

        (2)多重继承和虚继承的成本

        多重继承:如果一个类从多个基类继承,对象中会包含每个基类的子对象。这可能导致对象内存布局复杂化,增加内存开销。

        虚继承:虚继承用于解决菱形继承问题,但会引入额外的间接层(通过由虚基类指针实现),增加内存和运行时开销。

class A { int a; };
class B : virtual public A { int b; };
class C : virtual public A { int c; };
class D : public B, public C { int d; };

int main() {
    D obj;
    std::cout << "Size of D: " << sizeof(obj) << std::endl;  // 可能比预期大
    return 0;
}

        (3)RTTI(运行时类型识别)成本

        RTTI 允许在运行时获取对象的类型信息,但这需要编译器为每个类生成额外的类型信息,并存储在内存中。使用dynamic_cast时,还需要遍历继承链,增加了运行时开销。

        内存开销:RTTI 会增加程序的内存占用,尤其是对于大型类层次结构。

class Base { virtual void foo() {} };
class Derived : public Base {};

int main() {
    Base* obj = new Derived();
    if (Derived* d = dynamic_cast<Derived*>(obj)) {
        std::cout << "Downcast successful" << std::endl;
    }
    delete obj;
    return 0;
}

        (4)异常处理的成本

        异常机制:C++ 的异常处理需要在运行时维护额外的栈帧信息和异常表,这会增加程序的内存和运行时开销。

        性能影响:即使没有抛出异常,异常处理机制也会对性能产生一定影响,尤其是在函数调用和返回时。

void riskyFunction() {
    throw std::runtime_error("Something went wrong!");
}

int main() {
    try {
        riskyFunction();
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
    }
    return 0;
}

        (5)模版实例化成本

        代码膨胀:模板会在编译时为每种类型生成独立的代码实例,这可能导致生成的目标文件体积增大。

        编译时间:模板的实例化会增加编译时间,尤其是在模板代码复杂或模板参数类型较多时。

template <typename T>
class Box {
public:
    T value;
    void set(T v) { value = v; }
    T get() { return value; }
};

int main() {
    Box<int> intBox;
    Box<double> doubleBox;
    return 0;
}

        (6)对象构造和析构的成本

        构造函数和析构函数调用:在复杂的类层次结构中,构造和析构对象可能需要调用多个构造函数和析构函数,增加了运行时开销。

        异常安全:如果构造函数抛出异常,需要确保已分配的资源被正确释放,这会增加额外的逻辑和开销。

class Resource {
public:
    Resource() { std::cout << "Resource acquired" << std::endl; }
    ~Resource() { std::cout << "Resource released" << std::endl; }
};

class Widget {
    Resource res;
public:
    Widget() { std::cout << "Widget created" << std::endl; }
    ~Widget() { std::cout << "Widget destroyed" << std::endl; }
};

int main() {
    Widget w;
    return 0;
}

        (7)内联函数的潜在成本

        代码膨胀:内联函数虽然减少了函数调用的开销,但会将函数体直接插入调用处,可能导致代码体积增大。

        缓存不友好:过度的内联可能导致指令缓存效率降低,影响性能。

inline int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(3, 4);
    return 0;
}

3.总结

        C++对象模型的额外成本主要来自以上七部分。这些特性使C++更加灵活的同时也增加了额外的成本。因此要合理使用C++的特性。

如有错误,敬请指正!!!


http://www.niftyadmin.cn/n/5865173.html

相关文章

硬件加速与技术创新双轮驱动:DeepSeek和ChatGPT性能进阶的未来蓝图

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ Linux网络编程笔记&#xff1a; https://blog.cs…

UE地编材质世界对齐纹理旋转

帖子地址 https://forums.unrealengine.com/t/how-to-rotate-a-world-aligned-texture/32532/4世界对齐纹理本身不能改 自己创建了个函数 把世界对齐纹理的内容赋值粘贴 在纹理偏移里给值 不要局限0-1 给值给大一点

deepseek本地部署,ragflow,docker

先下载ollama 1.官网下载 deepseek-r1:14bhttps://ollama.com/library/deepseek-r1:14b 2.GitHub下载GitHub - ollama/ollama: Get up and running with Llama 3.3, DeepSeek-R1, Phi-4, Gemma 2, and other large language models. 两种方式 安装完后&#xff0c;cmd-&g…

服务器广播需要广播的服务器数量

服务器广播需要广播的服务器数量 真题目录: 点击去查看 E 卷 100分题型 题目描述 服务器连接方式包括直接相连,间接连接。 A和B直接连接,B和C直接连接,则A和C间接连接。 直接连接和间接连接都可以发送广播。 给出一个N*N数组,代表N个服务器, matrix[i][j] == 1, 则…

3D Web轻量化引擎HOOPS Communicator如何赋能航空航天制造?

在当今航空航天制造领域&#xff0c;精确度、效率和协作是推动行业发展的关键要素。随着数字化技术的飞速发展&#xff0c;3D Web可视化开发包HOOPS Communicator 为航空航天制造带来了革命性的变化。它凭借强大的功能和灵活的应用&#xff0c;助力企业在设计、生产、培训等各个…

Python在实际工作中的运用-CSV数据的几个处理方法

相信工作时间较长的“表哥们”一定都遇到过需要对存在固定格式的一些比较特殊的CSV文件进行处理的工作&#xff0c;比如CSV文本是从数据库里导出的格式文本&#xff0c;此时如果CSV文件中再出现个什么像身份证号码这类超过15个字符的数据时&#xff0c;如采用Excel直接打开保存…

html中的元素(1)

​大家好&#xff01;我叫补三补四 欢迎学习讨论 ​ 常用属性 表单元素form用于创建提供用户输入的表单&#xff0c;常用属性 1.action&#xff1a;规定表单提交网址 2.method&#xff1a;规定提交方法是get还是post 3.enctype&#xff1a;规定编码方式 4.name&#xff1a;表…

在 Mac mini M2 上本地部署 DeepSeek-R1:14B:使用 Ollama 和 Chatbox 的完整指南

随着人工智能技术的飞速发展&#xff0c;本地部署大型语言模型&#xff08;LLM&#xff09;已成为许多技术爱好者的热门选择。本地部署不仅能够保护隐私&#xff0c;还能提供更灵活的使用体验。本文将详细介绍如何在 Mac mini M2&#xff08;24GB 内存&#xff09;上部署 DeepS…