官术网_书友最值得收藏!

Low-level details of objects

C++ does its best to support compatibility with the C language. While C structs are just a tool that allows us to aggregate data, C++ makes them equal to classes, allowing them to have constructors, virtual functions, inherit others structs, and so on. The only difference between a struct and a class is the default visibility modifier: public for structs and private for classes. There is usually no difference in using structs over classes or vice versa. OOP requires more than just a data aggregation. To fully understand OOP, let's find out how we would we incorporate the OOP paradigm if we have only simple structs providing data aggregation and nothing more. 

A central entity of an e-commerce marketplace such as Amazon or Alibaba is the Product, which we represent in the following way:

struct Product {
std::string name;
double price;
int rating;
bool available;
};

We will add more members to the Product if necessary. The memory layout of an object of the Product type can be pictured like this:

Declaring a Product object takes sizeof(Product) space in memory, while declaring a pointer or a reference to the object takes the space required to store the address (usually 4 or 8 bytes). See the following code block:

Product book;
Product tshirt;
Product* ptr = &book;
Product& ref = tshirt;

We can picture the preceding code as follows:

Let's start with the space the Product object takes in memory. We can calculate the size of the Product object summing up the sizes of its member variables. The size of a boolean variable is 1 byte. The exact size of the double or the int is not specified in the C++ standard. In 64-bit machines, a double variable usually takes 8 bytes and an int variable takes 4 bytes.

The implementation of std::string is not specified in the standard, so its size depends on the library implementation. string stores a pointer to a character array, but it also might store the number of allocated characters to efficiently return it when size() is called. Some implementations of std::string take 8, 24, or 32 bytes of memory, but we will stick to 24 bytes in our example. By summing it up, the size of the Product will be as follows:

24 (std::string) + 8 (double) + 4 (int) + 1 (bool) = 37 bytes.

Printing the size of the Product outputs a different value:

std::cout << sizeof(Product);

It outputs 40 instead of the calculated 37 bytes. The reason behind the redundant bytes is the padding of the struct, a technique practiced by the compiler to optimize the access to individual members of the object. The Central Processing Unit (CPU) reads the memory in fixed-size words. The size of the word is defined by the CPU (usually, it's 32 or 64 bits long). The CPU is able to access the data at once if it's starting from a word-aligned address. For example, the boolean data member of the Product requires 1 byte of memory and can be placed right after the rating member. As it turns out, the compiler aligns the data for faster access. Let's suppose the word size is 4 bytes. This means that the CPU will access a variable without redundant steps if the variable starts from an address that's divisible by 4. The compiler augments the struct earlier with additional bytes to align the members to word-boundary addresses.

主站蜘蛛池模板: 铜山县| 崇信县| 永新县| 隆子县| 五家渠市| 赤壁市| 呼玛县| 宣威市| 汶上县| 商河县| 平定县| 苏州市| 湖口县| 金秀| 韩城市| 铁岭县| 金山区| 会理县| 哈尔滨市| 柳州市| 曲松县| 封丘县| 色达县| 邻水| 尼木县| 页游| 丹东市| 海门市| 万山特区| 舟山市| 镇安县| 土默特右旗| 哈密市| 肃宁县| 延长县| 普格县| 前郭尔| 高唐县| 二连浩特市| 姚安县| 东港市|