我不明白的 C++ 行为
C++ behavior that I don't understand
我和我的朋友们正在玩 C++ 语言。在这样做的过程中,我们遇到了无法理解的问题。
代码如下:
#include <vector>
#include <iostream>
void print(std::vector<char> const &input)
{
std::cout << input.size();
for (int i = 0; i < input.size(); i++)
{
std::cout << input.at(i) << " - ";
}
}
int main()
{
char cha = 'A';
char chb = 'B';
char * pcha = &cha;
char * pchb = &chb;
try
{
std::vector<char> a = {pcha, pchb};
//std::vector<char> a = {pchb, pcha};
print(a);
}
catch(std::exception e)
{
std::cout << e.what();
}
}
此代码的输出:
A
当我注释掉第一行时,尝试阻止并取消注释第二行,结果是:
try
{
// std::vector<char> a = {pcha, pchb};
std::vector<char> a = {pchb, pcha};
print(a);
}
输出变为:
std:exception
我想这可能是因为声明的变量(char,char*)的填充和对齐方式不同导致的,但仍然不明白。您可以找到代码 here 来玩。
提前致谢。
std::vector<char> a = {pcha, pchb};
在这里,您使用 vector 的构造函数接受两个迭代器到一个范围。除非结束迭代器可以从开始迭代器到达,否则程序的行为是未定义的。您的两个指针不是同一范围的迭代器(即数组的元素),因此无法从另一个访问一个。因此程序的行为是未定义的。
这些是正确的:
std::vector<char> a = {cha, chb}; // uses initializer_list constructor
// or
char arr[] {cha, chb};
char * pcha = std::begin(arr);
char * pchb = std::end(arr);
std::vector<char> a = {pcha, pchb}; // uses the iterator constructor
@eerorika 的回答解释了你的错误。
但是,我想劝阻您和其他读者不要使用他的(?)更正代码片段的第二部分 - 不是因为它不正确,而是因为它是有问题的编码实践:
- 我接受 Nicolai Jossutis 的 suggestion 尝试用大括号统一初始化变量,因为(例如
mytype myvar {my_initializer};
)。
- 独立指针是危险的野兽。尝试完全避免它们,或将它们的存在最小化到您真正需要它们的地方。毕竟,您 "tempted" 以不恰当的方式使用了这些指针……所以,
char arr[] {cha, chb};
std::vector<char> a = {std::begin(arr), std::end(arr)};
- 不要为了创建您真正想要的容器而创建虚拟容器。只需坚持@eerorika 建议中的第一行(不带等号):
std::vector<char> a {cha, chb};
- 事实上,除非你真的需要它——你可能甚至不想创建一个可变长度的容器。所以也许只是
std::array<char, 2> a {cha, chb};
或者使用 C++17 的模板参数推导:
std::array a {cha, chb};
我和我的朋友们正在玩 C++ 语言。在这样做的过程中,我们遇到了无法理解的问题。
代码如下:
#include <vector>
#include <iostream>
void print(std::vector<char> const &input)
{
std::cout << input.size();
for (int i = 0; i < input.size(); i++)
{
std::cout << input.at(i) << " - ";
}
}
int main()
{
char cha = 'A';
char chb = 'B';
char * pcha = &cha;
char * pchb = &chb;
try
{
std::vector<char> a = {pcha, pchb};
//std::vector<char> a = {pchb, pcha};
print(a);
}
catch(std::exception e)
{
std::cout << e.what();
}
}
此代码的输出:
A
当我注释掉第一行时,尝试阻止并取消注释第二行,结果是:
try
{
// std::vector<char> a = {pcha, pchb};
std::vector<char> a = {pchb, pcha};
print(a);
}
输出变为:
std:exception
我想这可能是因为声明的变量(char,char*)的填充和对齐方式不同导致的,但仍然不明白。您可以找到代码 here 来玩。 提前致谢。
std::vector<char> a = {pcha, pchb};
在这里,您使用 vector 的构造函数接受两个迭代器到一个范围。除非结束迭代器可以从开始迭代器到达,否则程序的行为是未定义的。您的两个指针不是同一范围的迭代器(即数组的元素),因此无法从另一个访问一个。因此程序的行为是未定义的。
这些是正确的:
std::vector<char> a = {cha, chb}; // uses initializer_list constructor
// or
char arr[] {cha, chb};
char * pcha = std::begin(arr);
char * pchb = std::end(arr);
std::vector<char> a = {pcha, pchb}; // uses the iterator constructor
@eerorika 的回答解释了你的错误。
但是,我想劝阻您和其他读者不要使用他的(?)更正代码片段的第二部分 - 不是因为它不正确,而是因为它是有问题的编码实践:
- 我接受 Nicolai Jossutis 的 suggestion 尝试用大括号统一初始化变量,因为(例如
mytype myvar {my_initializer};
)。 - 独立指针是危险的野兽。尝试完全避免它们,或将它们的存在最小化到您真正需要它们的地方。毕竟,您 "tempted" 以不恰当的方式使用了这些指针……所以,
char arr[] {cha, chb}; std::vector<char> a = {std::begin(arr), std::end(arr)};
- 不要为了创建您真正想要的容器而创建虚拟容器。只需坚持@eerorika 建议中的第一行(不带等号):
std::vector<char> a {cha, chb};
- 事实上,除非你真的需要它——你可能甚至不想创建一个可变长度的容器。所以也许只是
或者使用 C++17 的模板参数推导:std::array<char, 2> a {cha, chb};
std::array a {cha, chb};