【问题标题】:Error: invalid operands of types ‘const char [35]’ and ‘const char [2]’ to binary ‘operator+’错误:“const char [35]”和“const char [2]”类型的无效操作数到二进制“operator+”
【发布时间】:2014-07-19 03:07:42
【问题描述】:

在我的文件顶部

#define AGE "42"

稍后在文件中我多次使用 ID,包括一些看起来像的行

1 std::string name = "Obama";
2 std::string str = "Hello " + name + " you are " + AGE + " years old!";
3 str += "Do you feel " + AGE + " years old?";

我得到错误:

“错误:‘const char [35]’和‘const char [2]’类型的无效操作数到二进制‘operator+’”

在第 3 行。我做了一些研究,发现这是因为 C++ 如何处理不同的字符串,并且能够通过将“AGE”更改为“string(AGE)”来修复它。但是,直到今天我不小心错过了其中一个实例,并且想知道为什么编译器没有抱怨,即使我仍然有一个只是“AGE”的实例。

通过一些试验和错误,我发现我只需要 string(AGE) 在我不连接在函数体中创建的另一个字符串的行上。

我的问题是“在后台发生了什么,C++ 不喜欢将字符串与预处理器放置的字符串连接起来,除非你也在连接你在函数中定义的字符串。”

【问题讨论】:

  • 感谢您的解释。尽管我决定摆脱宏,但我很高兴我知道“为什么”。

标签: c++ string c-preprocessor stdstring


【解决方案1】:

考虑一下:

std::string str = "Hello " + "world"; // bad!

operator + 的右轴和左轴都是char*s。没有operator + 的定义需要两个char*s(事实上,语言不允许你写一个)。结果,在我的编译器上,这会产生“无法添加两个指针”错误(您的显然是用数组来表达事物,但这是同样的问题)。

现在考虑一下:

std::string str = "Hello " + std::string("world"); // ok

有一个operator + 的定义,它将const char* 作为左轴,将std::string 作为右轴,所以现在每个人都很高兴。

您可以将其扩展到任意长度的串联链。不过,它可能会变得混乱。例如:

std::string str = "Hello " + "there " + std::string("world"); // no good!

这不起作用,因为您在将 lhs 转换为 std::string 之前尝试 + 两个 char*s。但这很好:

std::string str = std::string("Hello ") + "there " + "world"; // ok

因为一旦您转换为std::string,您可以根据需要+ 任意数量的其他char*s。

如果这仍然令人困惑,添加一些括号以突出显示关联性规则然后将变量名称替换为它们的类型可能会有所帮助:

((std::string("Hello ") + "there ") + "world");
((string + char*) + char*)

第一步是调用标准库中定义的string operator+(string, char*)。用它们的结果替换这两个操作数给出:

((string) + char*)

这正是我们刚刚所做的,并且仍然是合法的。但是尝试同样的事情:

((char* + char*) + string)

你被卡住了,因为第一个操作试图添加两个char*s。

故事的寓意:如果您想确保串联链能够正常工作,只需确保前两个参数中的一个显式类型为 std::string。

【讨论】:

  • 我有一个类似的代码throw out_of_range("ModuleName:: " __FUNCTION__ ": Exception message");,它用VS2010编译得很好。我不确定为什么或如何发生。但是当我尝试用 gcc 编译它时,我得到了错误。我最终不得不做类似throw out_of_range(string("ModuleName:: ") + __FUNCTION__ + ": Exception message");
  • @sabertooth1990 gcc 不是我的编译器,但通过快速查看它的文档,__FUNCTION__ 扩展的类型似乎是 char[]。您可以通过将它们全部写入一行来将字符串文字连接在一起,但这不适用于数组或指针。 vcc 必须将其视为文字。
  • 这也是因为operator+ 是左关联的。因此,以下表达式 "Do you feel " + "42" + " years old?" 变为 ("Do you feel " + "42") + " years old?" 并且编译器找不到可以处理此问题的方法。而当任何操作数(+ 的 LHS 或 RHS)中有 std::string 时,operator+ 具有处理字符串文字的重载方法。
  • 我不想暗示左边的字符串与其他字符串有任何不同,所以我从一个空字符串开始,然后连接你想要的所有字符串。 std::string value = std::string() + "Happy Birthday! You are now " + AGE + " years old";
【解决方案2】:

AGE 被定义为"42" 所以这一行:

str += "Do you feel " + AGE + " years old?";

转换为:

str += "Do you feel " + "42" + " years old?";

这是无效的,因为 "Do you feel " 和 "42" 都是 const char[]。要解决这个问题,您可以创建一个std::string,或者直接删除+:

// 1.
str += std::string("Do you feel ") + AGE + " years old?";

// 2.
str += "Do you feel " AGE " years old?";

【讨论】:

    【解决方案3】:

    在第 2 行中,涉及到一个 std::string (name)。有为char[] + std::string、std::string + char[]等定义的操作。"Hello " + name给出一个std::string,它被添加到" you are ",给出另一个字符串等等。

    在第 3 行,你在说

    char[] + char[] + char[]
    

    而且你不能只是相互添加数组。

    【讨论】:

      【解决方案4】:

      您不能像这样连接原始字符串。 operator+ 仅适用于两个 std::string 对象或一个 std::string 和一个原始字符串(在操作的任一侧)。

      std::string s("...");
      s + s; // OK
      s + "x"; // OK
      "x" + s; // OK
      "x" + "x" // error
      

      最简单的解决方案是先将原始字符串转换为std::string:

      "Do you feel " + std::string(AGE) + " years old?";
      

      当然,您一开始就不应该使用宏。 C++ 不是 C。请使用 const,或者在具有适当编译器支持的 C++11 中使用 constexpr。

      【讨论】:

      • 或者你可以删除+: "Do you feel " AGE
      • ... 这让其他程序员感到困惑,并为许多维护噩梦打开了空间。摆脱宏是最好的解决方案。
      • 不确定称它们为“原始字符串”是否合适
      【解决方案5】:

      在这种特殊情况下,更简单的解决方法是将“+”全部去掉,因为 AGE 是字符串文字,而之前和之后的也是字符串文字。您可以将第 3 行写为:

      str += "Do you feel " AGE " years old?";

      这是因为大多数 C/C++ 编译器会自动连接字符串文字。以上等价于:

      str += "Do you feel " "42" " years old?";

      编译器将转换为:

      str += "Do you feel 42 years old?";

      【讨论】:

        【解决方案6】:

        我的代码中遇到了同样的问题。我正在连接一个字符串以创建一个字符串。以下是部分代码。

        int scannerId = 1;
        std:strring testValue;
        strInXml = std::string(std::string("<inArgs>" \
                                "<scannerID>" + scannerId) + std::string("</scannerID>" \
                                "<cmdArgs>" \
                                "<arg-string>" + testValue) + "</arg-string>" \
                                "<arg-bool>FALSE</arg-bool>" \
                                "<arg-bool>FALSE</arg-bool>" \
                                "</cmdArgs>"\
                                "</inArgs>");
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-23
          相关资源
          最近更新 更多