String types
User
-
defined types
Pointer types
Strictly speaking, the C++ language has no built-in string type; char and wchar_t store single characters - you
must declare an array of these types to approximate a string, adding a terminating null value (for example, ASCII
'\0' ) to the array element one past the last valid character (also called a C-style string). C-style strings required
much more code to be written or the use of external string utility library functions. But in modern C++, we have
the Standard Library types std::string (for 8-bit char -type character strings) or std::wstring (for 16-bit
wchar_t -type character strings). These C++ Standard Library containers can be thought of as native string types
because they are part of the standard libraries that are included in any compliant C++ build environment. Simply
use the #include <string> directive to make these types available in your program. (If you are using MFC or ATL,
the CString class is also available, but is not part of the C++ standard.) The use of null-terminated character arrays
(the C-style strings previously mentioned) is strongly discouraged in modern C++.
When you define a class , struct , union , or enum , that construct is used in the rest of your code as if it were a
fundamental type. It has a known size in memory, and certain rules about how it can be used apply to it for
compile-time checking and, at runtime, for the life of your program. The primary differences between the
fundamental built-in types and user-defined types are as follows:
The compiler has no built-in knowledge of a user-defined type. It learns of the type when it first encounters
the definition during the compilation process.
You specify what operations can be performed on your type, and how it can be converted to other types, by
defining (through overloading) the appropriate operators, either as class members or non-member
functions. For more information, see Function Overloading.
They do not have to be statically typed (the rule that an object's type never changes). Through the
mechanisms of inheritance and polymorphism, a variable declared as a user-defined type of class (referred
to as an object instance of a class) might have a different type at run-time than at compile time. For more
information, see Inheritance.
Dating back to the earliest versions of the C language, C++ continues to let you declare a variable of a pointer type
by using the special declarator * (asterisk). A pointer type stores the address of the location in memory where the
actual data value is stored. In modern C++, these are referred to as raw pointers, and are accessed in your code
through special operators * (asterisk) or -> (dash with greater-than). This is called dereferencing, and which one
that you use depends on whether you are dereferencing a pointer to a scalar or a pointer to a member in an object.
Working with pointer types has long been one of the most challenging and confusing aspects of C and C++
program development. This section outlines some facts and practices to help use raw pointers if you want to, but in
modern C++ it’s no longer required (or recommended) to use raw pointers for object ownership at all, due to the
evolution of the smart pointer (discussed more at the end of this section). It is still useful and safe to use raw
pointers for observing objects, but if you must use them for object ownership, you should do so with caution and
very careful consideration of how the objects owned by them are created and destroyed.
The first thing that you should know is declaring a raw pointer variable will allocate only the memory that is
required to store an address of the memory location that the pointer will be referring to when it is dereferenced.
Allocation of the memory for the data value itself (also called backing store) is not yet allocated. In other words, by
declaring a raw pointer variable, you are creating a memory address variable, not an actual data variable.
Dereferencing a pointer variable before making sure that it contains a valid address to a backing store will cause
undefined behavior (usually a fatal error) in your program. The following example demonstrates this kind of error: