C++模板概念与基于范围循环(range-based for loop)的陷阱

2021-09-27
2903
0

有些人提到C 模板就会下意识地觉得可怕、看不懂、避而远之。其实模板并不复杂,而且熟练后可以用在日常工作中,可以帮助我们重用代码,让代码更简洁、易读、可维护。

 

希望这个系列的文章,能够让更多人发现模板的魅力,帮助大家写出更高质量的代码。

 

什么是模板?

 

顾名思义,模板就是编译器生成代码用的模子。模板有两类,函数模板和类模板(C 14开始出现了变量模板,不过不在此讨论)。如果想要生成函数代码,则需要用函数模板,如果想要生成类定义,则需要用到类模板。

 

 

我们为什么需要模板?

 

我们有时候会遇到这样的情况:同样的函数,我们要为不同的类型写不同的版本,内容与逻辑都是一摸一样的,只有他们的类型不一样。比如我们写一个max函数,传入两个数字,返回大的数字。

 

很自然地,两个参数的类型和返回的类型必须是相同的。如果不使用模板,我们需要使用函数重载,为不同的类型写不同的函数:

 

int max(int a, int b) {
    return a < b ? b: a;
}

float max(float a, float b) {
    return a < b ? b: a;
}

 

这里我只写了2个函数,实际上short, long, unsigned, double等等类型都需要专门的max函数,结果就是需要写十几个几乎一摸一样的代码。

 

如果函数功能更复杂一些,函数实现需要更多行,就会出现大量冗余重复的代码,而且不容易维护,很容易出错。这个时候如果我们能够根据特定的模板批量生成一系列代码,将会方便很;为此,我们可以使用C 中的模板。

 

 

C 基于范围循环(range-based for loop)的陷阱:

 

C 的基于范围的循环是C 11出现的新特性,很方便,一定程度上替代了使用迭代器的for循环用法。不过基于范围的for循环有一个隐藏的陷阱,如果不注意可能会出现严重的内存错误。

 

看下面这个代码:

 

1#include < iostream > 2#include < string > 3 4 using namespace std;
5 6 struct MyClass 7 {
    8 string text = "MyClass";
    9 10 string & getText() 11 {
        12
        return text;
        13
    }
    14
};
15 16 int main() 17 {
    18
    for (auto ch: MyClass().text) 19 {
        20 cout << ch;
        21
    }
    22 cout << endl;
    23
}

 

这个代码很简单,输出结果就是 "MyClass"。但如果稍微修改第18行,改为以下的样子:

 

for (auto ch: MyClass().getText()) {
    cout << ch;
}

 

结果什么都不会输出,程序直接退出。要理解为什么会出现这种行为,要先知道基于范围的for循环是怎么定义的。

 

基于范围的for循环定义:

 

在C 11标准中,它有以下的格式

 

1 attr(optional) for (range_declaration: range_expression) loop_statement

 

其中attr是可选的,range_declaration部分相当于我们代码中的 "auto ch",range_expression部分相当于 "MyClass().getText()",loop_statement就是 "{ cout << ch; }"

 

标准规定,上面的循环表达式应当等价于

 

{
    auto && __range = range_expression;
    for (auto __begin = begin_expr, __end = end_expr; __begin != __end; __begin) {
        range_declaration = *__begin;
        loop_statement
    }
}

 

 

转载声明:本文来源于网络,不作任何商业用途。

免责声明:本文内部分内容来自网络,所涉绘画作品及文字版权与著作权归原作者,若有侵权或异议请联系我们处理。
收藏

全部评论

您还没登录

暂无留言,赶紧抢占沙发
王氏教育是国内专业的CG数字艺术设计线上线下学习平台,在王氏教育,有原画、插画、漫画、影视、3D模型等培训课程,也有学习资源下载、行业社区交流。CG数字艺术学习,来王氏教育。
绘学霸iOS端二维码

IOS下载

绘学霸安卓端二维码

安卓下载

绘学霸微信小程序二维码

小程序

版权声明
本网站所有产品设计、功能及展示形式,均已受版权或产权保护,任何公司及个人不得以任何方式复制部分或全部,违者将依法追究责任,特此声明。
热线电话
18026259035
咨询时间:9:00~21:00
在线客服
联系网站客服
客服微信:18026259035
公司地址
中国·广州
广州市海珠区晓港中马路130号之19
绘学霸客户端(权限暂无,用于CG资源与教程交流分享)
王氏教育 王氏教育