class之位对齐

下面通过一个例子说明下位对齐及其位对齐的算法:

class A
{
int m;//4
char s;//1
double d;//8
int l;//4
};
void main()
{
 cout<<sizeof(A)<<endl;
 }

如果没有位对齐的话它输出的结果将会是4+1+8+4=17,可是事实是输出的24(32位机 vc6.0环境 当然和这个有关)其原因及其算法如下:

m占了4个字节所以是4,s占了1个字节而4是一的整数倍,所以为4+1=5,d占了8个字节,而5不是8的倍数所以要加上3变成8的倍数,所以就是5+3+8=16,l占了4个字节,16是4的倍数,所以为16+4=20。而因为总的大小要为class中最宽基本类型成员大小的整数倍,而这里最宽的是double既是8个字节,所以总的大小一定要为8的整数倍,而20不是8的整数倍,因此结果为:20+4=24.

其实位对齐的宽度是可以设置的,有两种设置方式如下:

1)在编译器里直接设置,即在vc6.0中直接设置,设置如下:

      project->settings->c/c++->Category(Code Generation)->Struct member alignment在这里可以设置。

2)可以用#pragma   pack(n)进行控制,方法如下:

     #include<iostream>
#include<string>
#pragma   pack(n)  // n为1,2,4,8,16

using namespace std;
class A
{
int m;//4
char s;//1
double d;//8
int l;//4
};
void main()
{
 cout<<sizeof(A)<<endl;
 } 

如果将n设置为1的话就是说对齐位的宽度为1,换句话说就是为1的整数倍,所以程序的运行结果就是:4+1+8+4=17

如果将n设置为2的话算法如下:

m为4是2的整数倍所以为4,s为1所以为4+1=5,可是5不是2的整数倍,所以是5+1+8=14,14+4=18,所以最后的结果是18.

其他的设置n的值是同理的。

 
为什么会有内存对齐?
    以下内容节选自《Intel Architecture 32 Manual》。
    字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自然边界分别是偶数地址,可以被4整除的地址,和可以被8整除的地址。)
    无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。
    一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。
    某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常(#GP)。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问内存中未对齐的数据。

简单一点说为什么会有位对齐,就是从cpu对内存的访问周期上考虑的,这样虽然是浪费了一点空间,可是加快了cpu的处理速度。

  以上是本人的见解,如有不对之处,希望大家多多指正。

<think>嗯,用户之前已经了解了C++类中的内存对齐规则,现在他们想进一步了解除了内存对齐之外,C++类还有哪些其他特性或行为。我需要整理这些特性,确保涵盖关键点,同时结构清晰。首先,我得回忆C++类的核心特性。比如访问控制、构造函数和析构函数、继承、多态、静态成员、友元、运算符重载、模板类、移动语义、虚函数表等等。这些都是类的重要特性,需要分门别类地解释。 用户可能对面向对象的基本概念有所了解,但需要系统性的总结。比如访问控制中的public、private、protected,这是类的基础,必须提到。构造函数和析构函数是对象生命周期的管理,包括复制控制函数(拷贝构造、赋值运算符)也是关键点。继承和多态是OOP的核心,要详细说明不同类型的继承(public、protected、private)以及虚函数和抽象类的概念。静态成员和友元函数/类属于类级别的特性,需要单独列出。 运算符重载和模板类属于高级特性,可以举例说明。移动语义是C++11引入的重要特性,涉及到右值引用和移动构造函数,这也是性能优化的关键点。虚函数表(vtable)和虚函数指针(vptr)虽然与内存布局相关,但属于多态的实现机制,应该作为独立的部分说明。此外,嵌套类、成员初始化列表、explicit关键字、委托构造函数等细节也不能遗漏。还需要考虑用户可能的实际应用场景,比如如何设计类、如何管理资源、如何实现多态等。示例代码能帮助理解,比如展示继承和多态的代码片段,或者移动语义的应用。 另外,引用之前提到的内存对齐相关内容时,要自然衔接,比如虚函数表指针对内存布局的影响已经在之前的讨论中涉及,这里可以简要提及,并引用之前的注释[^1][^3]。要确保回答结构清晰,分点列出,每个部分有简要说明和示例。同时,生成的相关问题需要引导用户深入探索,比如关于虚函数表的实现细节、移动语义的应用场景等。 最后,检查是否有遗漏的重要特性,比如RAII原则、const成员函数、mutable关键字、类型转换运算符等。这些虽然细节,但也是类的重要组成部分,需要适当提及。总结下来,需要组织成几个主要部分,每部分简明扼要,涵盖关键点,并附上示例和相关引用,确保用户能够全面了解C++类的其他特性。</think>### C++ 类的核心特性详解(除内存对齐外) --- #### 一、访问控制与封装 1. **访问修饰符** - `public`:允许类外访问 - `private`:仅类内和友元可访问 - `protected`:类内及子类可访问 ```cpp class BankAccount { private: double balance; // 数据隐藏 public: void deposit(double amount) { balance += amount; } // 暴露接口 }; ``` 2. **友元机制** 允许特定函数或类访问私有成员: ```cpp class Matrix { friend Matrix operator*(const Matrix& a, const Matrix& b); // 友元函数 friend class Printer; // 友元类 }; ``` --- #### 二、对象生命周期管理 1. **构造函数与析构函数** - 默认构造函数、拷贝构造函数、移动构造函数(C++11) - 析构函数自动释放资源(RAII原则) ```cpp class FileHandler { FILE* file; public: FileHandler(const char* path) { file = fopen(path, "r"); } // 构造函数 ~FileHandler() { if(file) fclose(file); } // 析构函数 }; ``` 2. **运算符重载** 自定义类型操作语义: ```cpp class Vector3D { float x, y, z; public: Vector3D operator+(const Vector3D& other) const { return {x+other.x, y+other.y, z+other.z}; } }; ``` --- #### 三、继承与多态 1. **继承类型** - `public`继承:基类成员访问权限不变 - `protected`继承:基类public成员变为protected - `private`继承:基类成员全变为private ```cpp class Shape { /*...*/ }; class Circle : public Shape { // public继承 virtual void draw() override; // 多态实现 }; ``` 2. **虚函数与动态绑定** - 虚函数表(vtable)实现运行时多态[^1][^3] - `override`和`final`关键字(C++11) ```cpp class Animal { public: virtual void speak() = 0; // 纯虚函数(抽象类) }; ``` --- #### 四、类模板与泛型编程 1. **模板类** 支持类型参数化: ```cpp template<typename T> class Stack { T* data; int top; public: void push(const T& item); }; ``` 2. **特化与偏特化** 针对特定类型优化实现: ```cpp template<> class Stack<bool> { // 全特化 // 压缩实现 }; ``` --- #### 五、高级特性(C++11及之后) 1. **移动语义** - 右值引用(`T&&`)避免深拷贝 - 移动构造函数与`std::move` ```cpp class StringBuffer { char* data; public: StringBuffer(StringBuffer&& other) noexcept // 移动构造 : data(other.data) { other.data = nullptr; } }; ``` 2. **委托构造函数** 构造函数复用逻辑: ```cpp class Config { public: Config() : Config("default") {} // 委托构造 Config(const char* path) { /*加载配置*/ } }; ``` 3. **成员初始化列表** 直接在类内初始化成员(C++11): ```cpp class Sensor { int sampling_rate = 1000; // 类内初始化 std::vector<double> buffer{1024}; // 统一初始化 }; ``` --- #### 六、静态成员与嵌套类 1. **静态成员** - 静态数据成员:类级别共享数据 - 静态成员函数:无`this`指针 ```cpp class Logger { static int log_count; // 声明 public: static void log(const std::string& msg); }; int Logger::log_count = 0; // 定义 ``` 2. **嵌套类** 类内部定义辅助类: ```cpp class Graph { class Node { // 嵌套类 int id; std::vector<Node*> neighbors; }; }; ``` --- #### 七、类型系统增强 1. **显式类型转换** - `explicit`关键字禁止隐式转换 ```cpp class DatabaseHandle { public: explicit DatabaseHandle(int port) {} // 必须显式构造 }; ``` 2. **类型转换运算符** 自定义类型转换行为: ```cpp class SmartBool { public: explicit operator bool() const { return state; } }; ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值