`
javayestome
  • 浏览: 1008102 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

避免劣化代码(No Inferior Code)之一

阅读更多

刀不磨会生锈,久了不编程,也会忘记很多关键的东西,其中之一就是会把日常编程中应当注意的问题忘记,慢慢地写的代码就很烂了,不忍卒读.....

编程是一门细致活儿,有很多陷阱,其中之一是我们容易编写劣化的代码,相当多的人都想不通自己写的代码怎么写都没有人家的执行起来有效率,所以在这里我就写一些自己掌握的这方面的知识,一来是防止自己忘却,二来是与大家分享,特别是初学编程者。

相当一部分人会认为我写出来的内容应该算是代码优化层面,我是不这样认为的。我认为编程中优化不可过早,但避免劣化代码却要时刻进行。我这里谈的内容有些是老生常谈,那我就深入挖掘,力求旧瓶有新酒;有些是鲜为人知,那我就详言细述,力求深入浅出。

关于避免代码劣化这个话题,将不限于C和C++两种语言,还包括python,lua等大家熟悉的脚本语言,甚至是boost,OpenMP等学用的库,也许还会见到SQL语句的优化等,希望大家多多捧场~

本系列文章欢迎转载、打印、分发等,但不可用于商业用途,任何时候必须保留全文完整,并声明转载自恋花蝶的博客(http://blog.csdn.net/lanphaday),谢谢。

避免劣化代码(一)
No Inferior Code(1)
条款1尽量使用拷贝构造函数初始化实例变量,而非使用赋值操作符进行初始化。
例:
#include <ctime>
#include <iostream>
#include <string>
void test_inferior_code(int cnt, const char* str)
{
for(int i = 0; i < cnt; ++i)
{
std::string s;
s = str;
s[0] = 'H';
}
}
void test_excellent_code(int cnt, const char* str)
{
for(int i = 0; i < cnt; ++i)
{
std::string s(str);
s[0] = 'H';
}
}
int main()
{
static const int cnt = 1000000;
char str[] = "hello";
clock_t bgn = clock();
test_inferior_code(cnt, str);
clock_t end = clock();
std::cout << "test_inferior_code used " << end-bgn << "ms\n";
bgn = clock();
test_excellent_code(cnt, str);
end = clock();
std::cout << "test_excellent_code used " << end-bgn << "ms\n";
return 0;
}
分析:
在我的机器(配置和编译执行环境见文后)上,上例的输出如下:
$ ./no_inferior_code1.exe
test_inferior_code used 4336ms
test_excellent_code used 3485ms
可以看到使用赋值操作符的版本执行时间是使用拷贝构造函数方式的1.2倍。这个数值并不算惊人,但绝不能不重视之;因为例子只是使用了std::string,如果是有多个元素的std::map呢,如果是用户自定义的类呢?所以勿以善小而不为,勿以恶小而为之,养成尽量使用拷贝构造函数的习惯非常重要。
上面的例子不太可能出现在我们的代码中,现实中最容易出现这种劣化代表的情况是这样的:
class A
{
public:
A(const std::string& str){_str = str;}
private:
std::string _str;
};
这样的代码很容易看到,其实就是一种劣化的代码。比较好的写法是这样的:
public:
A(const std::string& str):_str(str){}
使用构造列表来初始化成员变量。
扩展:
一路谈来都是使用STL等别人的库,那么如果自己要写一个类给其他人使用的时候,应该注意些什么吗?是的,我们应该提供能让他人写出excellent代码的接口或者方法。简单地说,如果我们提供的类重载了赋值操作符,那么就应该相应地提供一个拷贝构造函数;反过来,如果提供了拷贝构造函数,那也需要重载赋值操作符。如果你并不打算这样做,那一定要把你不提供的接口声明为private或者protected,以免编译器自动生成它,造成误会。
class A
{
public:
A(const A& a):_str(a._str){}
A& operator=(const A& a){_str = a.str;return *this;}
std::string str;
};
上面的代码是一个还算过得去的例子~
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics