C++我不理解的行为

C++ behavior that I don't understand

本文关键字:不理解 C++      更新时间:2023-10-16

我和我的朋友们在玩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();
}
}

此代码的输出:

一个

当我注释掉第一行时,请尝试阻止并取消注释第二行,这是这样的:

try
{
// std::vector<char> a = {pcha, pchb};
std::vector<char> a = {pchb, pcha};
print(a); 
}

输出变为:

标准:异常

我想这可能是因为声明的变量(char、char*(的填充和对齐方式不同而发生的,但仍然不明白。你可以在这里找到代码来玩。 提前谢谢。

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的回答解释了你的错误。

但是,我想劝阻您和其他读者不要使用他(?(更正的代码片段的第二部分 - 不是因为它不正确,而是因为它是有问题的编码实践:

  1. 我接受尼古拉·约苏蒂斯的建议,即尝试用大括号统一初始化变量,并且没有等号(例如mytype myvar {my_initializer};(。
  2. 独立式指针是危险的野兽。尽量完全避免它们,或者将它们的存在最小化到你真正需要它们的地方。毕竟,你被"诱惑"以不恰当的方式使用这些指针......所以
    char arr[] {cha, chb};
    std::vector<char> a = {std::begin(arr), std::end(arr)};
    
  3. 不要仅仅为了创建您真正想要的容器而创建一个虚拟容器。只需坚持@eerorika建议中的第一行(不带等号(:
    std::vector<char> a {cha, chb}; 
    
  4. 事实上,除非你真的需要它 - 你可能甚至不想创建一个可变长度的容器。所以也许只是
    std::array<char, 2> a {cha, chb}; 
    
    或者用 C++17 的模板参数推导:
    std::array a {cha, chb};