将字符推送到字符串向量时出现意外行为

Unexpected behavior when pushing a character to vector of strings

我试图通过先将字符转换为字符串来将字符插入到字符串向量中,但情况 1 不起作用,但情况 2 有效。有人可以解释这种行为吗?有没有将 char 直接插入 vector 的解决方法?

    // vector of strings
    vector lt; std::string gt; out; 
    // EDIT - stack overflow is not letting me post "less than" sign so using lt; and gt; instead

    // a character
    char ch;

    // assign some value to ch and push to vector

    // CASE 1: don't work
    out.push_back("" + ch);

    // CASE 2: works
    string str = "";
    out.push_back(str + ch);

PS - 我正在使用 C++14

此代码编译并工作:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main() {
   // vector of strings

   vector<string> out;

   // a character
   char ch;

   // assign some value to ch and push to vector

   // Case 0: works because a const char * can be coerced into a string
   out.push_back("");

   // Case 1: Does not work 
   // you can't add a const char * and a char.
   // Some compilers coerce the char into an int and add that to the pointer
   // producing undefined behavior (access to un-allocated memory)
   // out.push_back("" + ' ');

   // CASE 1a: Works, but I'm 'cheating' by 
   // explicitly constructing a string.
   out.push_back(string("") + ch);

   // Case 1b: Works using a different string constructor
   // This is probably the best approach:
   out.push_back(string(1, ' '));

   // CASE 2: works
      string str = "";
      out.push_back(str + ch);

   std::cout << "out contains " << out.size() << " entries" << std::endl;

   return 0;
}

结果:

out contains 3 entries

术语 "" 不代表 std::string 实例,而是 const char* 文字,因此当您向其添加 ch 时,您正在执行指针运算并且可能会收到一条编译器警告:

warning: array subscript is above array bounds

push_back 一个 char 作为一个 std::string 到一个 std::vector<std::string> 只需做:

std::vector<std::string> vec;
char ch = 'a';
vec.push_back(std::string()+ch); // construct empty std::string, add ch, push_back

您的代码有问题。 这是类型特征,可帮助您检查名称是否为模板化类型:

/***Check if type is simple template***/
template <template<class...> class>
constexpr bool is_template_type()
{ return true; }

template <class>
constexpr bool is_template_type()
{ return false; }

有了这个,您可以检查 vector 是否是创建变量的有效类型。所以:

static_assert(!is_template_type<vector>(), 
              "vector is not valid type for creating a variable");

导致编译失败,因为无法创建class template的变量。您必须指定 TYPEstd::vector 应该存储。你的问题标题是:

vector of strings

所以您应该创建 std::vector<std::string> 变量。


您的代码的另一个问题是: "" + ch。 你认为它有什么作用? ""类型为char const[1]ch类型为charchar const[1] 可隐式转换为 char const *,并且由于您可以将整数值添加到指针 - 它可以编译。但这不是你想要的!

这是你的 "" 记忆:

`[=12=]' ? ? ? ? ? ? ...
/\

ch 添加到 "" 后,结果如下:

//ch is 5 for example
`[=13=]' ? ? ? ? ? ? ...
             /\

所以你用一些未指定的地址创建了 std::string。实际上,访问数组 out-of-bounds 是 C++ 中的未定义行为。

您应该使用 std::string() + ch 或用户 W.F 的字符串文字语法。发表在他对你的问题的评论中。


另外不要忘记初始化ch,因为使用未指定的值也是未定义的行为。