Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

ANSI/ISO C++ Professional Programmer''''s Handbook phần 9 pot
MIỄN PHÍ
Số trang
33
Kích thước
96.1 KB
Định dạng
PDF
Lượt xem
1202

ANSI/ISO C++ Professional Programmer''''s Handbook phần 9 pot

Nội dung xem thử

Mô tả chi tiết

Put differently, the statement

C* p = new C;

is transformed by the compiler into something similar to the following:

#include <new>

using namespace std;

class C{/*...*/};

void __new() throw (bad_alloc)

{

C * p = reinterpret_cast<C*> (new char [sizeof ]); //step 1: allocate

// raw memory

try

{

new (p) C; //step 2: construct the objects on previously allocated buffer

}

catch(...) //catch any exception thrown from C's constructor

{

delete[] p; //free the allocated buffer

throw; //re-throw the exception of C's constructor

}

}

Alignment Considerations

The pointer that is returned by new has the suitable alignment properties so that it can be converted to a pointer of

any object type and then used to access that object or array. Consequently, you are permitted to allocate character

arrays into which objects of other types will later be placed. For example

#include <new>

#include <iostream>

#include <string>

using namespace std;

class Employee

{

private:

string name;

int age;

public:

Employee();

~Employee();

};

void func() //use a pre allocated char array to construct

//an object of a different type

{

char * pc = new char[sizeof(Employee)];

Employee *pemp = new (pc) Employee; //construct on char array

//...use pemp

pemp->Employee::~Employee(); //explicit destruction

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 11 - Memmory Management

file:///D|/Cool Stuff/old/ftp/1/1/ch11/ch11.htm (11 von 23) [12.05.2000 14:46:34]

delete [] pc;

}

It might be tempting to use a buffer that is allocated on the stack to avoid the hassle of deleting it later:

char pbuff [sizeof(Employee)];

Employee *p = new (pbuff ) Employee; //undefined behavior

However, char arrays of automatic storage type are not guaranteed to meet the necessary alignment requirements of

objects of other types. Therefore, constructing an object of a preallocated buffer of automatic storage type can result

in undefined behavior. Furthermore, creating a new object at a storage location that was previously occupied by a

const object with static or automatic storage type also results in undefined behavior. For example

const Employee emp;

void bad_placement() //attempting to construct a new object

//at the storage location of a const object

{

emp.Employee::~Employee();

new (&emp) const Employee; // undefined behavior

}

Member Alignment

The size of a class or a struct might be larger than the result of adding the size of each data member in it. This is

because the compiler is allowed to add additional padding bytes between members whose size does not fit exactly into

a machine word (see also Chapter 13). For example

#include <cstring>

using namespace std;

struct Person

{

char firstName[5];

int age; // int occupies 4 bytes

char lastName[8];

}; //the actual size of Person is most likely larger than 17 bytes

void func()

{

Person person = {{"john"}, 30, {"lippman"}};

memset(&person, 0, 5+4+8 ); //may not erase the contents of

//person properly

}

On a 32-bit architecture, three additional bytes can be inserted between the first and the second members of Person,

increasing the size of Person from 17 bytes to 20.

On some implementations, the memset() call does not clear the last three bytes of the member lastName.

Therefore, use the sizeof operator to calculate the correct size:

memset(&p, 0, sizeof(Person));

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 11 - Memmory Management

file:///D|/Cool Stuff/old/ftp/1/1/ch11/ch11.htm (12 von 23) [12.05.2000 14:46:34]

The Size Of A Complete Object Can Never Be Zero

An empty class doesn't have any data members or member functions. Therefore, the size of an instance is seemingly

zero. However, C++ guarantees that the size of a complete object is never zero. Consider the following example:

class Empty {};

Empty e; // e occupies at least 1 byte of memory

If an object is allowed to occupy zero bytes of storage, its address can overlap with the address of a different object.

The most obvious case is an array of empty objects whose elements all have an identical address. To guarantee that a

complete object always has a distinct memory address, a complete object occupies at least one byte of memory.

Non-complete objects -- for example, base class subobjects in a derived class -- can occupy zero bytes of memory.

User-Defined Versions of new and delete Cannot Be

Declared in a Namespace

User-defined versions of new and delete can be declared in a class scope. However, it is illegal to declare them in

a namespace. To see why, consider the following example:

char *pc;

namespace A

{

void* operator new ( size_t );

void operator delete ( void * );

void func ()

{

pc = new char ( 'a');

}

}

void f() { delete pc; } // A::delete or ::delete?

Declaring new and delete in namespace A is confusing for both compilers and human readers. Some programmers

might expect the operator A::delete to be selected in the function f() because it matches the operator new that

was used to allocate the storage. In contrast, others might expect delete to be called because A::delete is not

visible in f(). For this reason, the Standardization committee decided to disallow declarations of new and delete

in a namespace.

Overloading new and delete in a Class

It is possible to override new and delete and define a specialized form for them for a given class. Thus, for a class

C that defines these operators, the following statements

C* p = new C;

delete p;

invoke the class's versions of new and delete, respectively. Defining class-specific versions of new and delete

is useful when the default memory management scheme is unsuitable. This technique is also used in applications that

have a custom memory pool. In the following example, operator new for class C is redefined to alter the default

behavior in case of an allocation failure; instead of throwing std::bad_alloc, this specific version throws a

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 11 - Memmory Management

file:///D|/Cool Stuff/old/ftp/1/1/ch11/ch11.htm (13 von 23) [12.05.2000 14:46:34]

Tải ngay đi em, còn do dự, trời tối mất!