这是书中P83的源码示例,测试范围for和cctype头文件中对字符串中单个字符的处理;
本人测试环境:Ubuntu16.04 LTS,GCC 5.4.0
测试源码 :
//
// for_toupper.cpp
//
#include <iostream>
#include <string>
#include <cctype> // 用于改变字符串中某个字符的特性
using namespace std;
int main()
{
string str("hello world");
for (auto &c : str)
c = toupper(c);
for (auto c : str)
cout << c;
cout << endl;
}
编译:
g++ for_toupper.cpp
错误打印:
for_toupper.cpp:10:14: error: ISO C++ forbids declaration of ‘c’ with no type [-fpermissive]
for (auto &c : str)
^
for_toupper.cpp:10:18: warning: range-based ‘for’ loops only available with -std=c++11 or -std=gnu++11
for (auto &c : str)
^
for_toupper.cpp:13:13: error: ‘c’ does not name a type
for (auto c : str)
^
for_toupper.cpp:15:3: error: expected ‘;’ before ‘cout’
cout << endl;
^
for_toupper.cpp:16:1: error: expected primary-expression before ‘}’ token
}
^
for_toupper.cpp:16:1: error: expected ‘)’ before ‘}’ token
for_toupper.cpp:16:1: error: expected primary-expression before ‘}’ token
错误分析:
第一行大致是说“声明无类型变量”,翻译过来大致意思就是说,基于范围for中的auto关键字编译器无法识别;
第二行是关键,编译器警告:范围for必须是C++11标准才能用(这其实我是知道的),进一步的意思是,编译器不支持C++11;
编译器版本是5.4(从4.7开始已经支持c++11),为什么就不支持呢?
第二行之后的错误信息都是同一原因,不具体分析了;
分析到这儿,问题基本清楚了:
- 源码本身没有问题,是源码中新标准的语法与编译器默认使用的语法标准不兼容
- 默认使用旧标准,如C++98,C++99,而auto关键字在旧标准和新标准用的含义是完全不同的,范围for语法只在新标准中支持
- 根据编译警告提示,在编译时指定使用C++标准的版本即可解决问题
正确的编译命令:
g++ for_toupper.cpp -std=c++11
思考:
这让我想起最近一直在优化的公司项目的旧代码,里面使用的makefile编译参数也没有指定特别版本(代码年龄比我本人还大,使用默认版本一般也不会出问题),不过,只要能在编译阶段能发现的问题,还能算是问题吗?
换到平时学习过程中写测试代码时,还是要养成一个好习惯:通过makefile把一些必要的编译参数加上,不然很可能的结果是:明明自己写测试代码没问题,为什么放到实际项目中就编译不过呢?
参考: