C++ Data types
When programming in a programming language, various variables are needed to store various kinds of information. A variable retains the memory location of the value it stores. This means that when you create a variable, some space is reserved in memory.
You may need to store information of various data types (such as character, wide character, integer, floating-point, double floating-point, boolean, etc.). The operating system will allocate memory based on the variable's data type and decide what to store in the reserved memory.
Basic built-in types
C++ provides programmers with a rich variety of built-in data types and user-defined data types. The following table lists seven basic C++ data types:
| Type | Keywords |
|---|---|
| Boolean type | bool |
| Character type | char |
| integer | int |
| Floating-point type | float |
| Double floating-point type | double |
| Void | void |
| Wide character type | wchar_t |
In fact, wchar_t is derived like this:
typedef short int wchar_t;
Therefore, wchar_t actually occupies the same space as short int.
Some basic types can be modified with one or more type modifiers:
| Modifiers | Description | Example |
|---|---|---|
signed | Indicates signed type (default) | signed int x = -10; |
unsigned | Denotes unsigned type | unsigned int y = 10; |
short | Denotes a short integer type | short int z = 100; |
long | Denotes a long integer type | long int a = 100000; |
const | Indicates constant, value cannot be modified | const int b = 5; |
volatile | Indicates that the variable may be modified unexpectedly, prohibiting compiler optimization. | volatile int c = 10; |
mutable | Indicates class members can beconstModified in the object | mutable int counter; |
The following table shows the memory required for various variable types when storing values in memory, as well as the maximum and minimum values that a variable of that type can store.
Note:There may be differences between different systems; one byte is 8 bits.
Note:By default, int, short, and long are signed.
Note:long int is 8 bytes, and int is always 4 bytes. Early C compilers defined long int as occupying 4 bytes and int as occupying 2 bytes. The newer C/C++ standards are compatible with this early setting.
| Data types | Description | Size (bytes) | Range/Value example |
|---|---|---|---|
bool | Boolean type, representing true or false | 1 | trueorfalse |
char | Character type, usually used to store ASCII characters. | 1 | -128 to 127 or 0 to 255 |
signed char | Signed character type | 1 | -128 to 127 |
unsigned char | Unsigned character type | 1 | 0 to 255 |
wchar_t | Wide character type, used to store Unicode characters. | 2 or 4 | Platform-dependent |
char16_t | 16-bit Unicode character type (introduced in C++11) | 2 | 0 to 65,535 |
char32_t | 32-bit Unicode character type (introduced in C++11) | 4 | 0 to 4,294,967,295 |
short | short integer | 2 | -32,768 to 32,767 |
unsigned short | Unsigned short integer | 2 | 0 to 65,535 |
int | integer | 4 | -2,147,483,648 to 2,147,483,647 |
unsigned int | Unsigned integer type | 4 | 0 to 4,294,967,295 |
long | long integer | 4 or 8 | Platform-dependent |
unsigned long | Unsigned long integer | 4 or 8 | Platform-dependent |
long long | Long long integer (introduced in C++11) | 8 | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
unsigned long long | Unsigned long long integer (introduced in C++11) | 8 | 0 to 18,446,744,073,709,551,615 |
float | Single-precision floating point | 4 | Approximately ±3.4e±38 (6-7 significant digits) |
double | Double-precision floating point | 8 | Approximately ±1.7e±308 (15 significant digits) |
long double | Extended-precision floating point | 8, 12, or 16 | Platform-dependent |
New types added in C++11
| Data types | Description | Example |
|---|---|---|
auto | Automatic type deduction | auto x = 10; |
decltype | Obtain the type of an expression | decltype(x) y = 20; |
nullptr | Null pointer constant | int* ptr = nullptr; |
std::initializer_list | Initializer list type | std::initializer_list<int> list = {1, 2, 3}; |
std::tuple | Tuple type, which can store multiple values of different types. | std::tuple<int, float, char> t(1, 2.0, 'a'); |
Note that the storage size of various types is related to the system bit width, but currently the mainstream is mainly 64-bit systems.
The following lists the differences in storage size between 32-bit systems and 64-bit systems (Windows is the same):
From the table above, it can be seen that the size of variables will vary depending on the compiler and the computer being used.
The following example will output the size of various data types on your computer.
Example
This example usesendl, this will insert a newline character after each line,<<Operators are used to pass multiple values to the screen,sizeof()The operator is used to obtain the size of various data types.
When the above code is compiled and executed, it will produce the following results, which may vary depending on the computer used:
type: ************size************** bool: 所占字节数:1 最大值:1 最小值:0 char: 所占字节数:1 最大值: 最小值:? signed char: 所占字节数:1 最大值: 最小值:? unsigned char: 所占字节数:1 最大值:? 最小值: wchar_t: 所占字节数:4 最大值:2147483647 最小值:-2147483648 short: 所占字节数:2 最大值:32767 最小值:-32768 int: 所占字节数:4 最大值:2147483647 最小值:-2147483648 unsigned: 所占字节数:4 最大值:4294967295 最小值:0 long: 所占字节数:8 最大值:9223372036854775807 最小值:-9223372036854775808 unsigned long: 所占字节数:8 最大值:18446744073709551615 最小值:0 double: 所占字节数:8 最大值:1.79769e+308 最小值:2.22507e-308 long double: 所占字节数:16 最大值:1.18973e+4932 最小值:3.3621e-4932 float: 所占字节数:4 最大值:3.40282e+38 最小值:1.17549e-38 size_t: 所占字节数:8 最大值:18446744073709551615 最小值:0 string: 所占字节数:24 type: ************size**************
Derived data types
| Data types | Description | Example |
|---|---|---|
Array | A collection of elements of the same type | int arr[5] = {1, 2, 3, 4, 5}; |
Pointer | A type that stores the memory address of a variable | int* ptr = &x; |
Reference | Variable alias | int& ref = x; |
Function | Function type, representing the signature of a function | int func(int a, int b); |
Struct | User-defined data type, which can contain multiple members of different types. | struct Point { int x; int y; }; |
Class | User-defined data type, supporting encapsulation, inheritance, and polymorphism. | class MyClass { ... }; |
Union | Multiple members share the same block of memory | union Data { int i; float f; }; |
Enum | A user-defined set of integer constants | enum Color { RED, GREEN, BLUE }; |
Type alias
| Alias | Description | Example |
|---|---|---|
typedef | Define an alias for an existing type | typedef int MyInt; |
using | Define an alias for an existing type (introduced in C++11) | using MyInt = int; |
Standard library type
| Data types | Description | Example |
|---|---|---|
std::string | String type | std::string s = "Hello"; |
std::vector | Dynamic Array | std::vector<int> v = {1, 2, 3}; |
std::array | Fixed-size array (introduced in C++11) | std::array<int, 3> a = {1, 2, 3}; |
std::pair | A container that stores two values | std::pair<int, float> p(1, 2.0); |
std::map | Key-value pair container | std::map<int, std::string> m; |
std::set | Unique value set | std::set<int> s = {1, 2, 3}; |
typedef declaration
You can usetypedefGive a new name to an existing type. The following is the syntax for defining a new type using typedef:
typedef type newname;
For example, the following statement tells the compiler that feet is another name for int:
typedef int feet;
Now, the following declaration is completely legal; it creates an integer variable distance:
feet distance;
Enumeration type
Enumeration type (enumeration) is a derived data type in C++, which is a collection of several enumeration constants defined by the user.
If a variable has only a few possible values, it can be defined as an enumeration type. The so-called "enumeration" means listing the values of the variable one by one, and the value of the variable can only be within the range of the listed values.
To create an enum, you need to use the keywordenum. The general form of an enum type is:
enum 枚举名{
标识符[=整型常数],
标识符[=整型常数],
...
标识符[=整型常数]
} 枚举变量;
If the enumeration is not initialized, i.e., when "= integer constant" is omitted, it starts from the first identifier.
For example, the following code defines a color enumeration, and the type of variable c is color. Finally, c is assigned the value "blue".
enum color { red, green, blue } c;
c = blue;
By default, the value of the first name is 0, the value of the second name is 1, the value of the third name is 2, and so on. However, you can also assign a special value to a name by simply adding an initial value. For example, in the following enumeration,greenThe value is 5.
enum color { red, green=5, blue };
Here,bluehas a value of 6, because by default, each name is 1 greater than the name before it, but the value of red is still 0.
Type conversion
Type conversion is the conversion of a value of one data type into a value of another data type.
There are four types of type conversion in C++: static conversion, dynamic conversion, const conversion, and reinterpret conversion.
Static Cast
Static conversion is the forced conversion of a value of one data type into a value of another data type.
Static conversion is usually used for conversions between objects of similar types, for example, converting an int type to a float type.
Static cast does not perform any runtime type checking, so it may lead to runtime errors.
Example
Dynamic Cast
Dynamic conversion (dynamic_cast) is a mechanism in C++ used for downcasting in an inheritance hierarchy.
Dynamic conversion is usually used to convert a base class pointer or reference into a derived class pointer or reference.
Dynamic cast performs type checking at runtime. If the conversion fails, it returns nullptr for pointer types, and throws a std::bad_cast exception for reference types.
Syntax:
dynamic_cast<目标类型>(表达式)
Target type: Must be a pointer or reference type.
Expression: The base class pointer or reference that needs to be converted.
Example: Dynamic cast of pointer types
Output:
Derived class method
Example: Dynamic cast of reference types
#include <typeinfo>
class Base {
public:
virtual ~Base() = default; // The base class must have virtual functions
};
class Derived : public Base {
public:
void show() {
std::cout << "Derived class method" << std::endl;
}
};
int main() {
Derived derived_obj;
Base& ref_base = derived_obj; // Base class reference bound to derived class object
try {
// Convert base class reference to derived class reference
Derived& ref_derived = dynamic_cast<Derived&>(ref_base);
ref_derived.show(); // Conversion successful, call derived class method
} catch (const std::bad_cast& e) {
std::cout << "Dynamic cast failed: " << e.what() << std::endl;
}
return 0;
}
Output:
Derived class method
| Features | Pointer type | Reference type |
|---|---|---|
| Return value on conversion failure | returnnullptr | Throwstd::bad_castException |
| Applicable scenarios | Downcasting, runtime type checking | Downcasting, runtime type checking |
| Performance overhead | Higher | Higher |
| Base class requirement | Must have virtual functions | Must have virtual functions |
Const Cast
Const conversion is used to convert an object of const type into an object of non-const type.
Const conversion can only be used to cast away the const attribute; it cannot change the type of the object.
Example
Reinterpret Cast
Reinterpret conversion reinterprets a value of one data type as a value of another data type, usually used for conversions between different data types.
Reinterpret conversion does not perform any type checking, which may lead to undefined behavior.
