C ++动态内存分配奇怪的输出
C++ dynamic memory allocation weird output
我正在学习 C++ 中的动态内存分配。在 运行 下面的代码中,每次都会打印不同的输出。
char *const dynamic_array = new char[50];
dynamic_array[0] = '[=10=]';
dynamic_array[0] = 'a';
cout << dynamic_array << endl;
delete[] dynamic_array;
5 次运行的示例输出:
- δ
- δ
- aⁿ
- aΓ
- aε
为什么某些运行的输出不同?
您在此呼叫的operator<<
:
cout << dynamic_array << endl;
需要指向空终止字符数组第一个元素的指针。您的字符数组不是以 null 结尾的,因此您的代码具有未定义的行为。
如果你想要一个动态大小的字符串,你应该这样写:
std::string dynamic_array{"a"};
std::cout << dynamic_array;
这与动态内存分配无关,只与遗留的 C 字符串有关。 C 字符串是一个 null 终止 字符数组。由于您未能在 'a'
之后正确写入空字符 ('[=10=]'
),将其用作 C 字符串是未定义的行为。
在C++中,变量和对象需要声明和初始化,但取决于特定变量是局部变量、class-成员变量还是global/static变量,它们的默认初始化可能由编译器完成,也可能不完成,遵循此处描述的规则:https://en.cppreference.com/w/cpp/language/default_initialization
简而言之就是局部变量不进行默认初始化,而static/global变量进行默认初始化。 class 成员变量的关注点是,如果构造函数中没有成员初始化语法(默认构造函数就是这种情况),那么它们也会被默认初始化。
关于此未初始化变量问题和 C++ 中的其他未定义行为,要记住的另一件事是,某些编译器可能决定(基于某些启发式或默认情况下)在声明时默认初始化所有变量以避免 运行-time 逻辑错误,这可能并不总是可取的(主要是由于性能原因),但可以禁用它们。阅读本文的一个很好的起点是:https://www.learncpp.com/cpp-tutorial/uninitialized-variables-and-undefined-behavior/
这与动态内存分配无关。即使您使用没有 new[]
:
的固定本地数组,您的代码也会失败
char fixed_array[50];
fixed_array[0] = '[=10=]';
fixed_array[0] = 'a';
cout << fixed_array << endl;
您正在调用以 nul 终止的 char*
字符串作为输入的重载 operator<<
,但您只是将 '[=16= ]'
终止符在错误的数组元素中。
改用这个:
char *const dynamic_array = new char[50];
dynamic_array[0] = 'a';
dynamic_array[1] = '[=11=]'; // <-- index 1, not 0!
cout << dynamic_array << endl;
delete[] dynamic_array;
char fixed_array[50];
fixed_array[0] = 'a';
fixed_array[1] = '[=12=]'; // <-- index 1, not 0!
cout << fixed_array << endl;
我正在学习 C++ 中的动态内存分配。在 运行 下面的代码中,每次都会打印不同的输出。
char *const dynamic_array = new char[50];
dynamic_array[0] = '[=10=]';
dynamic_array[0] = 'a';
cout << dynamic_array << endl;
delete[] dynamic_array;
5 次运行的示例输出:
- δ
- δ
- aⁿ
- aΓ
- aε
为什么某些运行的输出不同?
您在此呼叫的operator<<
:
cout << dynamic_array << endl;
需要指向空终止字符数组第一个元素的指针。您的字符数组不是以 null 结尾的,因此您的代码具有未定义的行为。
如果你想要一个动态大小的字符串,你应该这样写:
std::string dynamic_array{"a"};
std::cout << dynamic_array;
这与动态内存分配无关,只与遗留的 C 字符串有关。 C 字符串是一个 null 终止 字符数组。由于您未能在 'a'
之后正确写入空字符 ('[=10=]'
),将其用作 C 字符串是未定义的行为。
在C++中,变量和对象需要声明和初始化,但取决于特定变量是局部变量、class-成员变量还是global/static变量,它们的默认初始化可能由编译器完成,也可能不完成,遵循此处描述的规则:https://en.cppreference.com/w/cpp/language/default_initialization
简而言之就是局部变量不进行默认初始化,而static/global变量进行默认初始化。 class 成员变量的关注点是,如果构造函数中没有成员初始化语法(默认构造函数就是这种情况),那么它们也会被默认初始化。
关于此未初始化变量问题和 C++ 中的其他未定义行为,要记住的另一件事是,某些编译器可能决定(基于某些启发式或默认情况下)在声明时默认初始化所有变量以避免 运行-time 逻辑错误,这可能并不总是可取的(主要是由于性能原因),但可以禁用它们。阅读本文的一个很好的起点是:https://www.learncpp.com/cpp-tutorial/uninitialized-variables-and-undefined-behavior/
这与动态内存分配无关。即使您使用没有 new[]
:
char fixed_array[50];
fixed_array[0] = '[=10=]';
fixed_array[0] = 'a';
cout << fixed_array << endl;
您正在调用以 nul 终止的 char*
字符串作为输入的重载 operator<<
,但您只是将 '[=16= ]'
终止符在错误的数组元素中。
改用这个:
char *const dynamic_array = new char[50];
dynamic_array[0] = 'a';
dynamic_array[1] = '[=11=]'; // <-- index 1, not 0!
cout << dynamic_array << endl;
delete[] dynamic_array;
char fixed_array[50];
fixed_array[0] = 'a';
fixed_array[1] = '[=12=]'; // <-- index 1, not 0!
cout << fixed_array << endl;