【问题标题】:Is this string addition a valid expression?这个字符串加法是一个有效的表达式吗?
【发布时间】:2019-05-08 15:44:19
【问题描述】:

我很好奇复合赋值运算符是否对多个参数有效。我的猜测是 += 不会有副作用,但可能与 "-=" 的情况不同。

std::string a; 
a += "Hello" + " "+"World"; // doesn't compile
std::string name = "Old";
a += "Hello" + name +"World"; // compiles

【问题讨论】:

  • 你为什么不直接编译它以确定它是否有效?
  • @JesperJuhl 公平地说,并不是因为代码编译它才有效。
  • @FrançoisAndrieux 当然不是(我知道你知道我知道)。但它会让 OP 添加附加信息:“it compiles”或“it doesn't compile with this error: ...”。自己做一些基本的测试(比如“这甚至可以编译吗?”)是一个好习惯。
  • 他们(不是我)可能认为您在提出问题之前没有做足够的研究。这有点主观。

标签: c++ string operator-overloading string-literals user-defined-literals


【解决方案1】:

这不是一个有效的表达式,因为字符串文字没有运算符 +

"Hello" + " "+"World

(更准确地说是指针,因为在表达式中字符串文字很少有例外被转换为指向它们的第一个符号的指针。)

你可以写

std::string a; 
( ( a += "Hello" ) += " " ) += "World";

如果写出来会更易读

a += "Hello";
a += " ";
a += "World";

或者正如 @Bathsheba 在对我的回答的(有价值的)评论中指出的那样,您可以通过以下方式使用用户定义的字符串文字

#include <string>
#include <iostream>

int main()
{
    using namespace std::string_literals;
    std::string a; 
    a += "Hello"s + " " + "World";

    std::cout << a << '\n';
}

至于这个说法

a += "Hello" + name +"World";

然后可以使用为类std::basic_string定义的运算符重写它

template<class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs);

template<class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(basic_string<charT, traits, Allocator>&& lhs, const charT* rhs);

喜欢

a += operator +( operator +( "Hello", name ), "World" ); 

例如

#include <string>
#include <iostream>

int main()
{
    std::string a;
    std::string name = "Old";

    a += operator +( operator +( "Hello ", name ), " World" ); 

    std::cout << a << '\n';
}

考虑到每个运算符都返回一个类型为std::basic_string 的对象,operator + 是为其定义的。也就是说,在每次调用运算符时,都会出现一个 std::basic_string 类型的对象作为参数。

【讨论】:

  • 欢迎回来,弗拉德!
  • @Bathsheba 谢谢。很高兴认识你。:)
  • 如果你喜欢冒险,你也可以写 a += "Hello" " " "World" 甚至 ``a += "Hello World"`。
  • @DanM。你是对的,但问题是关于运算符 +。
  • @bruno:它有隐藏的深度。请注意,如果 a += b 真的被替换为 a = a + b,那么代码将编译。
【解决方案2】:

复合赋值运算符+= 没有加入。

您可以将+=std::string 一起使用,因为it defines the relevant overload,但它只能获得一个 参数。

并且您尝试将由+ing 多个字符串文字构造的表达式作为该参数传递。这不会编译。

一些替代品,在这个玩具案例中,可能会为您的真实案例提供解决方案:

选项 1

// Multiple calls to +=
std::string a;
a += "Hello";
a += " ";
a += "World";

选项 2

// String literal concatenation!
std::string a; 
a += "Hello" " " "World";

选项 3

// Repeated std::string concat
std::string a;
a += std::string("Hello") + " " + "World";

选项 4

// Same
using namespace std::string_literals;
std::string a; 
a += "Hello"s + " " + "World";

选项 5

// Don't bother
std::string a;
a += "Hello World";

【讨论】:

【解决方案3】:

表达式a += "Hello" + " " + "World"分组a += ("Hello" + " " + "World")

右侧是一组 3 个 const char[] 文字。当应用于二进制加法时,这些衰减到const char* 指针。由于无法添加指针,因此需要编译器发出诊断。

(请注意表面上等效的表达式a = a + "Hello" + " " + "World" 是可编译的。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 2018-04-21
    • 2016-10-18
    • 2014-05-01
    • 2021-04-12
    相关资源
    最近更新 更多