首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

运用STL会降低程序可读性?

2013-01-11 
使用STL会降低程序可读性??今天头一次自己做一个大模块。我图方便,循环使用了for_each 和 bind 组合起来用,

使用STL会降低程序可读性??
今天头一次自己做一个大模块。
我图方便,循环使用了for_each 和 bind 组合起来用,因为我实在讨厌写迭代器的声明;模块内部为了方便内存管理我都是使用了智能指针,然后typedef成一个XXXPtr的类型;而且也没有使用项目组里广泛使用的map,而是使用了unordered_map,因为我觉得能提高性能。
今天评审代码,说我的代码到处都是STL,可读性很差。“要是我读这个代码,肯定读不明白。”
我对说这话的同事印象还挺好的,人很聪明,而且能看的进去别人的代码。很多老旧的模块他都能看懂。
为啥他这样说呢?
STL真的会破坏可读性么?
[解决办法]
不能这么说吧。越是复杂,自然越要花功夫去读。
[解决办法]
他不懂stl而已。
当然,也不排除你stl使用上确实不标准。
[解决办法]
不会破坏可读性,读不明白是基础问题。。
[解决办法]
模块边界清楚不就行了。仅仅“到处都是STL”都能拿来当“可读性差”的堂皇的借口,八成说明读代码的水平太低,只是找不到个上台面的说法罢了。(虽然没看过LZ的代码也不能排除滥用或者有其它问题。)
只是懒得写迭代器类型,auto也就算了。
bind看你怎么用。
智能指针也一样,该用unique_ptr的地方不要用shared_ptr。
unordered_map是不是比map性能好,看需要什么操作。

[解决办法]

引用:
引用:只是懒得写迭代器类型,auto也就算了。
我们用的是VS2008 SP1,只有TR1中包含的扩展,没有完整的新C++特性。否则我也不需要用for_each不是?

没有lambda支持的for_each……恐怕大部分情况够呛。
[解决办法]
可能是你误用,也可能是对方不懂stl
如果是后者,这种态度不值得学习,作茧自缚

经验尚浅的我发现一个很讨厌的现象
对搞IT的人来说,所谓的“经验”有时候只是一种累赘
因为他们对XXX经验丰富,所以他们解决问题的时候
会倾向于把全部的问题都用XXX的方法解决
一旦遇到了自己没有接触过的技术,不同的做法
他们的态度除了排斥以外就是抹黑
完全没有一丝丝想学习的念头
对很多上了年纪的人来说这种现象更加普遍
出社会后最常见到的态度是“倚老卖老”
而非"活到老,学到老"
我很希望这只是我的错觉,或者只是年少轻狂的诳语

我个人是c过渡到c++的,妥善利用的话
不明白为何stl会导致可读性低

一个读取文件里头的double,排序并重新输出的程序

输入档
http://www.sendspace.com/file/4ypqdz

stl

//比较简洁,速度可能比较慢
void CPP_SOLUTION_ONE()
{  
  std::ifstream inFile("before.txt");
  std::vector<double> data( ( std::istream_iterator<double>(inFile) ), std::istream_iterator<double>() );
  std::sort(std::begin(data), std::end(data) );

  std::ofstream outFile("after.txt");
  std::copy(std::begin(data), std::end(data), std::ostream_iterator<double>(outFile, "\n") ); 
}

//比较烦杂,速度可能比较快
void CPP_SOLUTION_TWO()
{  
  FILE *fin = fopen("before.txt", "r");
  std::vector<double> data;
  double number = 0;
  while( fscanf(fin, "%lf", &number) == 1 ) data.push_back(number);

  fclose(fin);
  std::sort(std::begin(data), std::end(data) );

  std::ofstream outFile("after.txt");
  std::copy(std::begin(data), std::end(data), std::ostream_iterator<double>(outFile, "\n") );  
}


纯C

#include<stdlib.h>
#include<stdio.h>

int compare(void const *p, void const *q)
{
  double p0 = *(double*)p;
  double q0 = *(double*)q;

  if(p0 > q0) return 1;
  else if(p0 < q0) return -1;

  return 0;
}

void quit()
{
  fprintf(stderr, "memory exhausted\n");
  exit(1);
}

void C_SOLUTION()
{
  int res = 1000; //initial allocation



  double *buf = (double*)malloc(sizeof(double) * res);
  if(buf == 0) quit();

  int n = 0; //number of elements
  int i = 0;
  FILE *fin = fopen("before.txt", "rt");
  double d;
  while( fscanf(fin, "%lf", &d) == 1 )
  {
    if(n == res)
    {
      res += res;
      buf = (double*)realloc(buf, sizeof(double) * res );
      if(buf == 0) quit();
    }
    buf[n++] = d;
  }
  fclose(fin);
  qsort(buf, n, sizeof(double), compare);

  FILE *fout = fopen("after.txt", "wt");
  for(i = 0; i != n; ++i) fprintf(fout, "%f\n", buf[i]);

  fclose(fout);
  free(buf);
}



对于熟悉stl语法的人而已,那个比较容易阅读?
[解决办法]
既然你说广泛使用map,那么stl应该不是什么问题,主要问题大概在智能指针,说实话一般来说这东西真心没啥用,可读行还差
[解决办法]
>主要问题大概在智能指针,说实话一般来说这东西真心没啥用,可读行还差
不用smart pointer, 请问你要如何处理异常?
除非你完全不认为分配记忆体有可能抛出异常
否则手工处理只会让程式变得更加难阅读

smart pointer(RAII)在c++中扮演的角色太重要了
何况,unique_ptr在使用上跟一般的pointer差不多
不但让你轻易做到exception safe,还能省下一次
delete或free的麻烦呢

[解决办法]
对方觉得难阅读会不会是卡在stl的算法上面?
蛮多人对stl的算法不太熟悉

题外话,如果不支持lambda的话我也不喜欢用for_each
写起来太不顺手了
[解决办法]
引用:
>主要问题大概在智能指针,说实话一般来说这东西真心没啥用,可读行还差
不用smart pointer, 请问你要如何处理异常?
除非你完全不认为分配记忆体有可能抛出异常
否则手工处理只会让程式变得更加难阅读

smart pointer(RAII)在c++中扮演的角色太重要了
何况,unique_ptr在使用上跟一般的pointer差不多
不但让你轻易做到e……


智能指针实际上用的人并不多,智能指针和stl结合使用,稍有不慎会导致很多问题而且很难调试,看起来很好,其实很难用难维护,鸡肋一样的东西,一般除了系统封装好如com组件等,其他基本不用
[解决办法]
>智能指针和stl结合使用,稍有不慎会导致很多问题而且很难调试
这句话也可以改成
"raw pointer和stl结合使用,稍有不慎会导致很多问题而且很难调试"

>其实很难用难维护,鸡肋一样的东西
不靠smart pointer, 请问你如何处理exception?
每new一个物件就用try catch包裹起来?
这岂不是会多写很多重复的代码,导致程式更难维护?
或者你从来都不处理exception?

RAII是c++各大牛(BJ, Herb, Lippman, meyers, Alexandrescu等)
推荐的资源管理手法。既然你说这东西鸡肋,那么你平时是用什么方法
管理资源,让程式达到exception safe的标准?
如果有比smart pointer更好的方法,我很想知道也很想学习
如果你有更好的方法,能不能分享一下心得?谢谢
[解决办法]
引用:
如果每次new都要担心是否异常,这么大内存的使用,难道不用内存池的么?所有的分配只在内存池里面做,在这部分程序中加try catch就可以了


情况有这么单纯就好了

someObject *a = new someObject;
//do something and throw some exception
delete a;


此时a该怎么办?交给destructor处理?这不就是RAII吗?标准
已经有了两个很好的实作品,unique_ptr和shared_ptr了
我们为何不直接拿来用就好了呢?

另外一种更险恶的情况

[code]
class someClass{
  public :
    someClass() 
    {
      a = new someObject;


      //throw exception
      b= new someObject;
    }
    
    ~someClass() { delete a; delete b;}
};
[/code]
construct的动作还没完成,就抛出exception了
这种时候destructor根本不会执行,资源无法被释放

还有另外一种很常见的使用状况就是锁和解锁
[code]
std::mutex lk;

void mfunction(){
  lk.lock()
  //do something and throw exception
  lk.unlock(); //永远不会被解锁
}
[/code]
这会造成dead lock

我不喜欢exception,但是exception是c++的一部分
就算我不喜欢他也必须妥善的处理eception

以上的情况,除了RAII外,在c++中还有更好的方法解决吗?
不善用RAII就得到处加try...catch,程式更难维护
这是各c++的大牛大力推荐smart pointer(RAII)的理由之一
请问如果你有比RAII更好的方法吗?
[解决办法]
美化一下


class someClass{
  public :
    someClass() 
    {
      a = new someObject;
      //throw exception
      b= new someObject;
    }
    
    ~someClass() { delete a; delete b;}
private:
   someObject *a;
   someObject *b;
};



std::mutex lk;

void mfunction(){
  lk.lock()
  //do something and throw exception
  lk.unlock(); //永远不会被解锁
}

[解决办法]
for_each 和 bind 组合起来确实很难读(不是读懂读不懂的问题)最好写成局部的函数对象。

绝大多数场合是不需要unordered_map的,效率说不定还低于map。
[解决办法]
你得问他哪可读性差,是你写的不好,还是他不懂……
[解决办法]
引用:
引用:大量使用shared_ptr一定是作茧自缚
另外,RAII和shared_ptr可不是那么等同的。
要大量使用RAII,并且少用shared_ptr
为什么说大量使用shared_ptr是作茧自缚呢?能举个例子么?我使用shared_ptr没有特别的理由,就是觉得不需要自己释放内存了。那他的缺点体现在哪里呢?


在c++中大量使用smart pointer没什么不好的
早在c++98, 03时,meyers,herb,alexandrescu,lippman
就大力推荐我们将resource交给object保管(RAII)
极端的说,各大牛甚至认为在c++中
除了设计基础设施(data structure, smart pointer之类的)
其他情况下都不该让程式中出现delete
有delete代表你的程式可能出了问题(别忘了exception safe)

使用smart pointer(RAII)除了方便,更重要的是安全性
除了轻松达到exception safe的要求,也确保我们不会
忘记释放资源,当程式肥大起来时这个备忘功能就显得很重要了

c++最重要的精神之一就是zero overhead
shared_ptr需要计数,如果你不需要分享资源,就不要用shared_ptr
应该考虑使用uniqur_ptr,没有unique_ptr,也可以考虑scoped_ptr
什么东西都套上shared_ptr,代价有点高
[解决办法]
不熟悉stl的人看stl确实满蛋疼的,另外出了错也更麻烦一些
[解决办法]
引用:
引用:绝大多数场合是不需要unordered_map的,效率说不定还低于map。
hash查询和插入不是常数复杂度么?为啥大多数场合不需要呢?


一般来说
一是他比起red black tree更耗费空间
二是在资料量低的时候,map效率更高

我忽然想起另外一个滥用shared_ptr的情况

vector<shared_ptr<string>> weird_codes;


除非你要share那个string,否则这种情况根本没有使用shared_ptr的必要
shared_ptr没必要的话就少用点,多用unique_ptr(没的话可考虑auto_ptr)
smart pointer的精神是RAII,但不见得所有的资源都要交给smart pointer管理



这也是RAII


性能要求比较高,用c++98时顶多是这样写

A::iterator end = A.end();
for(A::iterator it = A.begin(); it != end; ++it){...}


在c++11中for_each大部分时候也可以用range based for loop取代

for(auto const &data : input){
...}


>搞C++真要非常熟悉STL才行
这点我赞同
[解决办法]
修改

A::iterator begin = A.begin();
A::iterator end = A.end();
for(it = begin; it != end; ++it){...}

[解决办法]
一个团队使用的技术和代码风格应该有一个标准,要不然每个人擅长的东西都不一样,大家写的代码谁也看起来不顺眼,岂不是很郁闷
[解决办法]
一直觉得代码的整体可读性比局部可读性重要得多.
小的代码片段再混乱,糟糕也是有限度的.而整体结构上的混乱那将是致命的.

stl对于不熟悉语法的人来说,的确是容易引起困扰.
即便是明白语法,如果不能完全掌握其实现细节,在有些时候还是会带来一些困扰.

热点排行