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

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

  1. 我接受 Nicolai Jossutis 的 suggestion 尝试用大括号统一初始化变量,因为(例如 mytype myvar {my_initializer};)。
  2. 独立指针是危险的野兽。尝试完全避免它们,或将它们的存在最小化到您真正需要它们的地方。毕竟,您 "tempted" 以不恰当的方式使用了这些指针……所以,
    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};