在 main 方法中声明与在 main 方法外部声明时的其他结果
other results when declaring in main method vs. outside from main method
我目前正在 codeforce 上做一个简单的问题。
基本上你得到一个字符串(例如“1+3+2”),你必须 return 它排序(例如“1+2+3”)。只会使用 1,2 和 3。
我开始于:
#include <iostream>
using namespace std;
int main()
{
string str;
int arr[4];
cin >>str;
for(int i = 0; i < str.length();i+=2)
arr[str[i] - '0']++;
}
我的想法是将每次出现的数字存储在一个数组中。但是如果我添加
我注意到一个问题
cout<< arr[2];
输入“1+2+3”,输出:
33
不过应该是1,因为3只出现过一次
我通过移动“string str;”解决了这个问题和“int arr[4]”,在 main:
#include <iostream>
using namespace std;
string str;
int arr[4];
int main()
{
cin >>str;
for(int i = 0; i < str.length();i+=2)
arr[str[i] - '0']++;
cout<< arr[2];
}
输出:
1
为什么它现在可以工作了?
您没有在第一个示例中初始化 int arr[4];
。 因此您的程序的行为是未定义的。
如果您在没有第一个 for 循环的情况下打印 arr
的内容:
for (auto x: arr) {
std::cout << x << "\n";
}
您得到的垃圾数据恰好位于 arr
的地址:
121
32584
615125669
22063
但你不能保证得到任何东西。如果您向编译器提供无效程序,它可以为所欲为。
您可以通过初始化数组来解决这个问题:
int arr[4] = {};
这将值初始化数组,对于int
意味着用0
初始化。
没有初始化器的自动存储持续时间:应用默认初始化:基本 non-class 类型的数组将保留未初始化的值
在您的第一个示例中,arr
具有自动存储持续时间并且未初始化,这是默认初始化的结果:
int main() {
// default initialization
int arr[4];
// reading from arr at this point (remains
// uninitialized) is undefined behaviour.
}
数组类型默认初始化的效果是数组的每个元素都是default-initialized。默认初始化对基本 non-class 类型没有任何影响:元素将保持未初始化状态。从这些元素中读取(在您的示例中对元素调用 operator++
)是未定义的行为。
你可以,例如value-initialize arr
使用以下语法:
int main() {
int arr[4]{};
}
数组的每个元素都是 value-initialized,这反过来又会导致数组(基本 non-class 类型)的每个元素都是 zero-initialized。
静态存储期限:zero-initialization 适用
第二个例子中,arr
不再是自动存储时长,而是静态存储时长,静态初始化的规则适用,会导致arr
为zero-initialized。
默认情况下,C++ 不会将数组初始化为 0。你的初始内容是不可预测的,你的结果也是如此。
有多种方法可以解决该问题。我建议使用 std::vector,像这样声明变量:
#include <vector>
std::vector<int> arr(4, 0);
第一个参数是大小,第二个是所有元素的初始值(默认为0)。您可以将它用作带 [] 的数组。它还有其他有用的功能,例如可以根据需要进行扩展。
或者,您也可以使用memset来清除数组:
#include <cstring>
memset(arr, 0, sizeof(arr));
此功能较旧,您需要更加小心。
我目前正在 codeforce 上做一个简单的问题。 基本上你得到一个字符串(例如“1+3+2”),你必须 return 它排序(例如“1+2+3”)。只会使用 1,2 和 3。
我开始于:
#include <iostream>
using namespace std;
int main()
{
string str;
int arr[4];
cin >>str;
for(int i = 0; i < str.length();i+=2)
arr[str[i] - '0']++;
}
我的想法是将每次出现的数字存储在一个数组中。但是如果我添加
我注意到一个问题cout<< arr[2];
输入“1+2+3”,输出:
33
不过应该是1,因为3只出现过一次
我通过移动“string str;”解决了这个问题和“int arr[4]”,在 main:
#include <iostream>
using namespace std;
string str;
int arr[4];
int main()
{
cin >>str;
for(int i = 0; i < str.length();i+=2)
arr[str[i] - '0']++;
cout<< arr[2];
}
输出:
1
为什么它现在可以工作了?
您没有在第一个示例中初始化 int arr[4];
。 因此您的程序的行为是未定义的。
如果您在没有第一个 for 循环的情况下打印 arr
的内容:
for (auto x: arr) {
std::cout << x << "\n";
}
您得到的垃圾数据恰好位于 arr
的地址:
121
32584
615125669
22063
但你不能保证得到任何东西。如果您向编译器提供无效程序,它可以为所欲为。
您可以通过初始化数组来解决这个问题:
int arr[4] = {};
这将值初始化数组,对于int
意味着用0
初始化。
没有初始化器的自动存储持续时间:应用默认初始化:基本 non-class 类型的数组将保留未初始化的值
在您的第一个示例中,arr
具有自动存储持续时间并且未初始化,这是默认初始化的结果:
int main() {
// default initialization
int arr[4];
// reading from arr at this point (remains
// uninitialized) is undefined behaviour.
}
数组类型默认初始化的效果是数组的每个元素都是default-initialized。默认初始化对基本 non-class 类型没有任何影响:元素将保持未初始化状态。从这些元素中读取(在您的示例中对元素调用 operator++
)是未定义的行为。
你可以,例如value-initialize arr
使用以下语法:
int main() {
int arr[4]{};
}
数组的每个元素都是 value-initialized,这反过来又会导致数组(基本 non-class 类型)的每个元素都是 zero-initialized。
静态存储期限:zero-initialization 适用
第二个例子中,arr
不再是自动存储时长,而是静态存储时长,静态初始化的规则适用,会导致arr
为zero-initialized。
默认情况下,C++ 不会将数组初始化为 0。你的初始内容是不可预测的,你的结果也是如此。
有多种方法可以解决该问题。我建议使用 std::vector,像这样声明变量:
#include <vector>
std::vector<int> arr(4, 0);
第一个参数是大小,第二个是所有元素的初始值(默认为0)。您可以将它用作带 [] 的数组。它还有其他有用的功能,例如可以根据需要进行扩展。
或者,您也可以使用memset来清除数组:
#include <cstring>
memset(arr, 0, sizeof(arr));
此功能较旧,您需要更加小心。