我有这个代码:
#includeusing namespace std; int main() { string name = "John "; int age = 32; name += age; cout << name << endl; return 0; }
代码编译成功但在运行时背叛,因为它默默地忽略连接部分并打印:
John
我知道我们需要使用stringstream来完成任务.但为什么上面的代码编译?因为以下代码:
#includeusing namespace std; int main() { string name = "John "; int age = 55; name = name + age; cout << name << endl; return 0; }
适当抛出和错误:
错误:'name + age'中的'operator +'不匹配
我从Java中知道,与前一个构造a += b
不同,a = a + b
将结果类型化为a的类型. 参考.但我认为这在C++中并不重要,因为我们总能做到:
int a = 1; float f = 3.33; a = a + f;
与Java不同,不必担心可能会丢失精确警告.需要在C++中引用它.
所以现在如果我们假设name += age;
扩展到name = string (name + age);
那时代码也不应该仅仅因为name + age不合法而编译.
您需要使用该-Wconversion
标志(我不清楚为什么它不包含在-Wall中)还可以查看请求或抑制警告的选项以获取更多详细信息.当我添加该标志时,我在使用时看到以下警告gcc
:
warning: conversion to 'char' from 'int' may alter its value [-Wconversion] name += age; ^
我们可以看到,运算符+ =确实支持char,因此转换后的值确实被添加到结尾name
,它根本不会忽略该操作.在C++中, operator + for std :: string是一个与operator + =不同的运算符.
在这个特定情况下:
name += age;
会翻译成这样的东西:
name.operator+=(static_cast<char>(age)) ;
如果我们有一个使用operator +的表达式而没有像这样的错误:
name = name + static_cast<char>( age );
会转化为:
operator+( name, static_cast<char>( age ) ) ;
在这个答案中很好地解释了为什么在你的例子中为operator +失败的原因,基本上模板函数不会执行转换,因此需要与const/volatile限定符的可能异常完全匹配.
Wconversion更新
gcc
有一个带有常见问题解答的Wconversion Wiki,它有点过时但它确实回答了为什么这个检查不包括在旗帜中:-Wall
隐式转换在C中非常常见.这与前端没有数据流(参见下一个问题)的结果相关,导致难以避免完美工作和有效代码的警告.Wconversion设计用于特定用途(安全审计,将32位代码移植到64位等),程序员愿意接受并解决无效警告.因此,如果未明确请求,则不应启用它.