# Chapter 19. Specialized Tools and Techniques
## 19.1 Controlling Memory Allocation
### 19.1.1 Overloading new and delete
An application can define `operator new` and `operator delete` functions in the global scope and/or as member functions.
The library defines eight overloaded versions of `operator new` and `delete` functions. The first four support the versions of `new` that can throw a `bad_alloc` exception. The next four support nonthrowing versions of `new`:
```cpp
// these versions might throw an exception
void *operator new(size_t); // allocate an object
void *operator new[](size_t); // allocate an array
void *operator delete(void*) noexcept; // free an object
void *operator delete[](void*) noexcept; // free an array
// versions that promise not to throw
void *operator new(size_t, nothrow_t&);
void *operator new[](size_t, nothrow_t&);
void *operator delete(void*, nothrow_t&) noexcept;
void *operator delete[](void*, nothrow_t&) noexcept;
```
The type `nothrow_t` is a `struct` defined in the `new` header. When defined as members of a class, these operator functions are implicitly static. The member `new` and `delete` functions must be static because they are used either before the object is constructed(`operator new`)or after it has been destroyed(`operator delete`).
An `operator new` or `operator new[]` function must have a return type of `void*` and its first parameter must have type `size_t`. That parameter may not have a default argument. The `operator new`z function is used when we allocate an object; `operator new[]` is called when allocating an array.
We can use functions named `malloc` and `free` that C++ inherits from C. These functions, are defined in `cstdlib`.
```cpp
void *operator new(size_t size) {
if (void *mem = malloc(size))
return mem;
else
throw ba_alloc();
}
void operator delete(void *mem) noexcept { free(mem); }
```
### 19.1.2 Placement new Expressions
```cpp
new (place_address) type;
new (place_address) type (initializers);
new (place_address) type [size];
new (place_address) type [size] { braced initializer list }
```
When passed a single argument that is a pointer, a placement `new` expression constructs an object but does not allocate memory.
```cpp
string *sp = new string("a value");
sp->~string();
```
Calling a destructor destroys an object but does not free the memory.
## 19.2 Run-Time Type Identification
Run-time type identification(RTTI) is provided through two operators:
* The `typeid` operator, which returns the type of a given expression
* The `dynamic_cast` operator, which safely converts a pointer or reference to a base type into a pointer or reference to a derived type.
### 19.2.1 Tye dynamic_cast Operator
A `dynamic_cast` has the following form:
```cpp
dynamic_cast<type*>(e);
dynamic_cast<type&>(e);
dynamic_cast<type&&>(e);
```
where `type` must be a class type and (ordinarily) names a class that has virtual functions.
We can do a `dynamic_cast` on a null pointer; the result is a null pointer of the requested type.
When a cast to a reference type fails, the cast throws an `std::bad_cast` exception, which is defined in the `typeinfo` library header.
```cpp
void f(const Base& b) {
try {
const Devrived& d = dynamic_cast<const Derived&>(b);
} catch (bad_cast) {
// handle the fact that the cast failed.
}
}
```
### 19.2.2 The typeid Operator
A `typeid` expression has the form `typeid(e)` where is `e` is any expression or a type name.
```cpp
if (typeid(*bp) == typeid(*dp)) {}
```
Whether `typeid` requires a run-time check determines whether the expression is evaluated.
### 19.2.3 Using RTTI
```cpp
bool operator==(const Base& lhr, const Base& rhs) {
return typeid(lhs) == typeid(rhs) && lhs.equal(rhs);
}
```
### 19.2.4 The type_info Class
| Operations on type_info | |
| ----------------------- | ------------------------------------------------------------ |
| t1 == t2 | Returns true if the type_info objects t1 and t2 refer to the same type, false otherwise. |
| t1 != t2 | Returns true if the type_info object t1and t2 refer to different types, false otherwise. |
| t.name() | Return a C-style character string that is a printable version of the type name. |
| t1.before(t2) | Returns a bool that indicates whether t1 comes before t2. |
The `type_info` class varies by the compiler. Some compilers provide additional member functions that provide additional information about types used in a program.
## 19.3 Enumerations
Enumerations let us group together sets of integral constants. Each enumeration defines a new type. Enumerations are literal types. C++ has two kinds of enumerations: scoped and unstopped. The new standard introduced scoped enumerations. We define a scoped enumeration using the keywords `enum` class, followed by the enumeration name and a comma-separated list of enumerators enclosed in curly braces.
```cpp
enum class open_modes {input, output, append};
```
We define an unscoped enumeration by omitting the class (or struct) keyword.
```cpp
enum color {red, yellow, green};
```
The names of the enumerators in a scoped enumeration follow normal scoping rules and are inaccessible outside the scope of the enumeration.
```cpp
enum color {red, yellow, green};
enum class peppers {red, yellow, green}; // ok: enumerators are hidden
color eyes = green; // ok: enumerators are in scope for an unscoped enumeration
peppers p = green; // error: enumerators from peppers are not in scope
color hair = color::red;
peppers p2 = peppers::red;
```
By default, enumerator values start at 0 and each enumerator has a value 1 greater than the preceding one. However, we can also supply initializers for one or more enumerators:
```cpp
enum class intTypes {
charTyp = 8, shortTyp = 16. intTyp = 16,
longTyp = 32, long_longTyp = 64
};
```
## 19.4 Pointer to Class Member
A pointer to member is a pointer that can point to a non-static member of a class.
```cpp
class Screen {
private:
std::string contents;
};
```
### 19.4.1 Pointers to Data Members
```cpp
// pdata can point to a string member of a const(or nonconst) Screen object
const string Screen::*pdata;
class Screen {
public:
static const std::string Screen::*data() { return &Screen::contents; }
};
const string Screen::*pdata = Screen::data();
```
### 19.4.2 Pointers to Member Functions
```cpp
auto pmf = &Screen::get_cursor;
char (Screen::*pmf2)(Screen::pos, Screen::pos) const;
pmf2 = &Screen::get;
Screen myScreen, *pScreen = &myScreen;
char c1 = (pScreen->*pmf)();
char c2 = (myScreen.*pmf2)(0, 0);
```
`myScreen.*pmf()` would be interpreted to mean `myScreen.*(pmf)`. This code says to call the function named `pmf` and use its return value as the operand fo the pointer-to-member operator `(.*)`. However, `pmf` is not a function, so this code is in error.
Type aliases or `typedefs` make pointers to members considerably easier to read.
```cpp
using Action = char (Screen::*)(Screen::pos, Screen::pos) const;
```
### 19.4.3 Using Member Functions as Callable Objects
One way to obtain a callable from a pointer to member function is by using the library `function` template:
```cpp
function<bool (const string&)> fcn = &stirng::empty;
```
Compiler deduce the member's type by using another library facility, `member_fn`, which, like `function`, is defined in the `functional` header. `men_fn` generates a callable object from a pointer to member. Unlike `function`, `meh_fn` will deduce the type of the callable from the type of the pointer to member:
```cpp
find_if(svec.begin(), svec.end(), mem_fn(&string::empty));
```
We can also use `bind` to generate a callable from a member function:
```cpp
auto it = find_if(svec.begin(), svec.end(), bind(&string::empty, _1));
```
## 19.5 Nested Classes
A class can be defined within another class. Such a class is a nested class, also referred to as a nested type.
Nested classes are independent classes and are largely unrelated to their enclosing class. In particular, objects of the enclosing and nested classes are independent of each other.
```cpp
class TextQuery {
public:
class QueryResult; // nested class to be defined later
};
class TextQuery::QueryResult {
};
```
## 19.6 union: A Space-Saving Class
A `union` is a special kind of class. A union may have multiple data members, but at any point in time, only one of the members may have a value.
A `union` can specify protection labels to make members `public`, `privaste` or `protected`. By default, like `structs`, members of a `union` are `public`. A `union` may define member functions, including constructors and destructors.
```cpp
// objects of type Token have a single member, which could be of any of the listed types
union Token {
char cval;
int ival;
double dval;
};
```
A `union` is defined starting with the keyword `union`, followed by a name for the `union` and a set of member declarations enclosed in curly braces.
```cpp
Token first_token = {'a'}; // initializes the cval member
Token last_token; // uninitialized Token object
Token *pt = new Token;
last_token.cval = 'z';
```
An anonymous union is an unnamed `union` that does not include any declarations between the close curly that end its body and the semicolon that ends the `union` definition.
```cpp
union {
char cval;
int ival;
double dval;
}; // defines an unnamed object, whose membrs we can access directly
cval = 'c';
ival = 42;
```
An anonymous `union` cannot have `private` or `protected members, nor can an anonymous `union` define member functions.
Under earlier versions of C++, `union` could not have members of a class type that defined its own constructors or copy-control members. Under the new standard, this restriction is lefted.
Because of the complexities involved in constructing and destroying members of class type, `unions` with class-type members ordinarily are embedded inside another class.
To keep track of what type of value the `union` holds, we usually define a separate object known as a discriminant.
```cpp
class Token {
public:
Token(): tok(INT), ival{0} {}
Token(const Token& t): tok(t.tok) { copyUnion(t); }
Token &operator=(const Token&);
~Token() { if (tok == STR) sval.~string(); }
};
```
## 19.7 Local Classes
A class can be defined inside a function body. Such a class is called a local class. A local class defines a type that is visible only in the scope in which it is defined.
A local class is not permitted to declare `static` data members there being no way to define them.
## 19.8 Inherently Nonportable Features
To support low-level programming, C++ defines some features that are inherently nonportable. A non-portable feature is one that is machine specific. Programs that use non-portable features often require reprogramming when they are moved from one machine to another.
### 19.8.1 Bit-fields
A class can define a (nonstatic) data member as a bit-field. A bit-field holds a specified number of bits. Bit-fields are normally used when a program needs to pass binary data to another program or to a hardware device.
The memory layout of a bit-field is machine-dependent.
```cpp
typedef unsigned int Bit;
class File {
Bit mode: 2;
Bit modified: 1;
enum modes { READ = 01, WRITE = 02, EXECUTE = 03 };
}
```
Ordinarily, it is best to make a bit-field an unsigned type. The behaviour of bit-fields stored in a `signed` type is implementation define.
### 19.8.2 volatile Qualifier
The precise meaning of `volatile` is inherently machine-dependent and can be understood only by reading the compiler documentation. Programs that use `volatile` usually must be changed when they are moved to new machines or compilers.
Programs that deal directly with hardware often have data elements whose value is controlled by processes outside the direct control of the program itself. For example, a programme might contain a variable updated by the system clock. An object should be declared `volatile` when its value might be changed in ways outside the control or detection of the program. The `volatile` keyword is a directive to the compiler that it should not perform optimizations on such objects.
```cpp
volatile int display_register;
volatile Task *curr_task;
volatile int iax[max_size];
volatile Screen bitmapBuf;
```
### 19.8.3 Linkage Directives: extern "C"
C++ uses linkage directives to indicate the language used for any non-C++ function.
Mixing C++ with code written in any other language, including C, requires access to a compiler for that language that is compatible with your C++ compiler.
```cpp
// single-statement linkage directive
extern "C" size_t strlen(const char*);
// compound-statement linkage directive
extern "C" {
int strcmp(const char*, const char*);
char *strcat(char*, const char*);
};
```
`extern "C" void (*pf)(int)`, some C++ compilers may accept the preceding assignment as a language extension, even though, strictly speaking, it is illegal.
- Introduction
- Chapter 1. Getting Start
- Chapter 2. Variables and Basic Types
- Chapter 3. String, Vectors, and Arrays
- Chapter 4. Expressions
- Chapter 5. Statements
- Chapter 6. Functions
- Chapter 7. Classes
- Chapter 8. The IO Library
- Chapter 9. Sequential Containers
- Chapter 10. Generic Algorithms
- Chapter 11. Associative Container
- Chapter 12. Dynamic Memory
- Chapter 13. Copy Control
- Chapter 14. Overloaded Operations and Conversions
- Chapter 15. Object-Oriented Programming
- Chapter 16. Template Argument Deduction
- Chapter 17. Specialized Library Facilities
- Chapter 18. Tools for Large Programs
- Chapter 19. Specialized Tools and Techniques
