可是,当设置断点单元测试时,却发现在红色代码之后,strMailFrom被处理成了
smtpagent/smtp_code/CMailMsgCoder.cppZ:Z"显得有些莫名其妙,为什么会突然多出来一个文件名呢?再进一步分析,strMailFrom = '<' + "\"" + strMailFrom + "\""这行代码,看上去就是把strMailFrom之前连上双引号,再连上尖括号,怎么会出错呢?从数据类型的角度分析,'<' + "\"" 是 char + const char * ,问题就在这里了。operator+ 操作符引起的隐式类型转换,编译器把指向char的指针加了一个偏移量,于是造成了内存偏移。
关于char + const char *,下面的例子可以作为一个佐证:
#include
int main()
{
std::string str;
str = 'C' + std::string("ab:cd");
std::cout << str << std::endl;
std::cout << 'C' + "^&*()" << std::endl;
return 0;
}
输出如下:
Cab:cd
^&*()
因为'C'的ASCII码值是67,所以第二行打印信息是从字符串的第68个字节开始打印。这种打印显然和预期中的相违背。
3 结论:解决方案及效果
把红色代码的字符串连接直接改写成下面的这句代码,问题就改正了。
strMailFrom = '<' + "\"" + strMailFrom + "\"";
改写为:
strMailFrom = "<\"" + strMailFrom + "\"";
因为发送方带标点时,走进了这段代码,产生了错误;而平时正常的情况下,发送方地址是不带标点的,直接执行strMailFrom = '<' + strMailFrom;所以,这个问题在平时不会暴露。
4 经验总结:预防措施和规范建议
一句看似没有问题的代码,却牵涉到C++底层的东西。这正是我们编程人员最需要去关注的知识。我们常常说,死都不知道是怎么死的,说的就是这种情况。
5 备注
我们写代码时,可以且仅可以使用如下的形式来实现字符串的相加:
std::string + std::string
std::string + const char *
const char * + std::string
std::string + char
char + std::string
下面的几种形式是不对的:
char + const char * 和 const char * + char
这个编译通过,但是语义不是字符串相加,而是指针加偏移值
const char * + const char * 这个还好,因为编译根本就通不过
6 考核点
字符串连接
7 试题
请选择不正确的字符串连接的语句:AB
A. std::string strTest = "this is a test"; strTest = "#" + "aaa" + strTest + "bbb" + "#";
B. std::string strTest = "this is a test"; strTest = '#' + "aaa" + strTest + "bbb" + '#';
C. std::string strTest = "this is a test"; strTest = "#aaa" + strTest + "bbb#";
阅读(330) | 评论(0) | 转发(0) |