【问题标题】:C++ string and overloaded operatorsC++ 字符串和重载运算符
【发布时间】:2015-11-12 23:36:54
【问题描述】:

我正在研究 C++ 库类型字符串。我正在研究该类型可以执行的操作,其中包括连接。 我知道在 C++ 中可以重载运算符以满足类类型的需要,而且我知道字符串文字是 const char 数组。 所以,我知道字符串类型定义了一个构造函数,它接受一个字符串字面量参数并将其转换为一个字符串,这样我就可以使用以下方法初始化一个字符串:

string s="hello!"

这里发生的是隐式转换(通过采用 const char* 的构造函数)到字符串,然后执行复制初始化(通过字符串的复制构造函数)。

到目前为止一切顺利..(如果我到目前为止有什么问题,请纠正我)

现在,我知道我可以连接两个字符串,或者我可以连接一个字符串和一个 char 文字(反之亦然)以及一个字符串和一个字符串文字(所以我想第一个发生是因为有一个重载的 + 运算符对称地接受一个 char 和一个字符串,后者的发生要归功于连接两个字符串的重载 + 运算符以及从 const char* 到字符串的隐式转换)。我的问题是:

1: 为什么我不能连接两个字符串文字?不应该调用带有两个字符串的operator+(并执行从const char*到字符串的两次隐式转换)?

string s="hi"+" there";

2:我尝试连接一个 char 文字和一个字符串文字(调用接受一个 char 和一个字符串的 operator+)但我在结果字符串中只得到垃圾,因为编译器不介意,但结果是当然不是我想要的。

string s='h'+"ello!";
cout<<s<<endl;

我把垃圾拿出来了。如果存在 operator+(char,const string&) 应该在将“ello”隐式转换为字符串后调用它,不是吗?

你能解释一下吗?

【问题讨论】:

  • 1) 不,因为它着眼于 operator+ 的重载指针,你不会在两个操作数上得到隐式转换。这没有多大意义 2) Cannot repro
  • string s="hello!"其实只是使用了const char *的字符串构造函数,没有进行拷贝初始化
  • @awesomeyi 这也不完全正确。首先,从"hello" 参数构造一个临时的string,然后通过直接初始化移动(或在C++03 中复制)到s 变量。
  • @awesomeyi:(附加到 dyp 的注释)...除非编译器执行 copy elision,在这种情况下,它实际上不会创建和复制临时文件,而是直接初始化。 (§12.8 复制类对象)这仍然需要一个可用的复制构造函数。
  • 虽然您没有问:要从其他两个生成单个字符串文字,您可以依靠预处理来附加它们:string s = "hello" " world"; 或者,在 C++14 及更高版本中,您可以使用 std::string 文字:using namespace std::literals::string_literals; auto s = "hello"s + " world";.

标签: c++ string operator-overloading string-concatenation


【解决方案1】:

1) 连接两个字符串字面量。

"Hello" + " world"

编译器没有提示它应该寻找与std::string相关的任何东西——它正在寻找两个const char[]对象,而你不能+那些(或@ 987654325@ 他们可以降级到)。

2) 在 char 文字和字符串文字上使用 operator+

(感谢用户 dyp 指出正确的方向。)

如果您字面意思是指char 字面量——例如'a' -- 那么你正在与 C/C++ 必须提供的更令人惊讶的事情之一发生冲突。

考虑一下:a[i] 等价于i[a](这是事实。)

所以,如果你写:

'a' + "Hello"

...相当于(在 ASCII 中)...

"Hello" + 97

...这是一个无处可去的指针,即从中构造一个std::string 是未定义的行为。

【讨论】:

  • 是的,但是您应该能够将这些 const char* 转换为两个字符串,然后使用重载的 operator+(const string&,const string&) ?
  • @Luca:请提供代码。简单的英语并不能很准确地说明您正在尝试做什么。
  • @Luca:你可以std::string( "Hello" ) + " world",当然,因为那么编译器确实知道看对于std::string::operator+
  • @DevSolar 好的,我现在得到了指针,但是第一个问题呢?我的意思是,当我连接一个字符串和一个字符串文字(就像你说的那样)时,为什么编译器可以弄清楚要调用什么重载运算符但它无法猜测我何时使用两个字符串文字(这是两个 const char 数组,或两个指向 const char 的指针,因此可以由接受该类型参数的字符串构造函数转换)?
  • @Luca:为什么它更愿意将那些const char * 变成std::string,而不是把它们变成int 并添加它们?一种转化的可能性与另一种转化的可能性一样。这就是为什么不允许那种“我只转换一切”的原因。
【解决方案2】:

Borgleader 已经在评论中给出了一半的答案:

  1. 当添加两个字符串时,编译器只看到两个const char *,它们可以转换为字符串,也可以转换为整数。所以除非你明确说你想要它们作为字符串,否则你会得到一个错误

  2. 当添加一个字符串litteral 和一个char 时,编译器会看到一个指针和一个整数。它知道如何处理它并对你的 C 字符串进行指针运算——这可能不是你所期望的!您有可能在 char 数组的末尾结束并调用未定义的行为。例子:

    "abc" + '0' => "abc" + 48 : 44 positions past the NULL ...
    "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij" + '0' => "ij"
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    • 2012-09-24
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    相关资源
    最近更新 更多