Refresh

This website coolshell.cn/articles/date/2012/09 is currently offline. Cloudflare's Always Online™ shows a snapshot of this web page from the Internet Archive's Wayback Machine. To check for the live version, click Refresh.

Browsed by
月度归档: 2012年9月

C/C++语言中闭包的探究及比较

C/C++语言中闭包的探究及比较

感谢投稿人 @思禽饮霜 

这里主要讨论的是C语言的扩展特性block。该特性是Apple为C、C++、Objective-C增加的扩展,让这些语言可以用类Lambda表达式的语法来创建闭包。前段时间,在对CoreData存取进行封装时(让开发人员可以更简洁快速地写相关代码),我对block机制有了进一步了解,觉得可以和C++ 11中的Lambda表达式相互印证,所以最近重新做了下整理,分享给大家。

0. 简单创建匿名函数

下面两段代码的作用都是创建匿名函数并调用,输出Hello, World语句。分别使用Objective-C和C++ 11:

^{ printf("Hello, World!\n"); } ();
[] { cout << "Hello, World" << endl; } ();

Lambda表达式的一个好处就是让开发人员可以在需要的时候临时创建函数,便捷。

在创建闭包(或者说Lambda函数)的语法上,Objective-C采用的是上尖号^,而C++ 11采用的是配对的方括号[]

不过“匿名函数”一词是针对程序员而言的,编译器还是采取了一定的命名规则。

比如下面Objective-C代码中的3个block,

#import <Foundation/Foundation.h>

int (^maxBlk)(int , int) = ^(int m, int n){ return m > n ? m : n; };

int main(int argc, const char * argv[])
{
    ^{ printf("Hello, World!\n"); } ();

    int i = 1024;
    void (^blk)(void) = ^{ printf("%d\n", i); };
    blk();

    return 0;
}

会产生对应的3个函数:

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (18 人打了分,平均分: 3.89 )
Loading...
对九个超级程序员的采访

对九个超级程序员的采访

原文:《Q&A With Nine Great Programmers》时间有限,我只能粗译,难免错误。

这篇访谈源自2006年,最先发布在波兰程序员 Jaroslaw “sztywny” Rzeszótko (AKA “Stiff”) 的博客上。但是这篇博文现在找不到了。非常感谢他能授权我重新发布这个博文。

在一个炎热无聊的下午,我突发奇想。我想通过电子邮件的方式对那些我非常感兴趣和非常敬重的程序员问10个问题。准备这10个问题我只花了5分钟,这些都是我个人想问他们的问题,所以,我基本上没想太多要问他们什么。最后两个问题和编程没有什么关系,我就是想问题这些人的一些兴趣爱好。另外,不是每一个人都想回答我的,这是我第一次做“访谈”,所以,我犯了一些错误,一些问题没有得到回答。不管怎么样,我得到了很多很有意思的内容,所以,这对我绝对是一次很有意义的经历。

并不是每一个人都回了我的邮件,也并不是每一个人都同意回答我的这些问题,也许在我发布这篇文章后我会得到那些回答,但是我已经迫不及待想把这些东西发布了,所以,我可能会更新这篇文章(更新:2006年3月8日,我收到了Bjarne Stroustrup的回信

— Jaroslaw

介绍

  • Dave Thomas – “Pragmatic Programmer”(注:douban) 和 “Programming Ruby”(注:douban) 以及其它一些优秀书籍的作者。 你可以在 这里 读读他对编程的一些想法。
  • Steve Yegge – 他可能并不那么知名,但是他给了很多有意思的回答。他有一个很火的关于编程的 blog,他也是游戏 “Wyvern” 的作者。(陈皓注:他最火的是去年在google+上对google和amazon的吐槽,06年他应该在google了)
好烂啊有点差凑合看看还不错很精彩 (27 人打了分,平均分: 4.04 )
Loading...
无锁队列的实现

无锁队列的实现

————注:本文于2019年11月4日更新————

关于无锁队列的实现,网上有很多文章,虽然本文可能和那些文章有所重复,但是我还是想以我自己的方式把这些文章中的重要的知识点串起来和大家讲一讲这个技术。下面开始正文。

关于CAS等原子操作

在开始说无锁队列之前,我们需要知道一个很重要的技术就是CAS操作——Compare & Set,或是 Compare & Swap,现在几乎所有的CPU指令都支持CAS的原子操作,X86下对应的是 CMPXCHG 汇编指令。有了这个原子操作,我们就可以用其来实现各种无锁(lock free)的数据结构。

这个操作用C语言来描述就是下面这个样子:(代码来自Wikipedia的Compare And Swap词条)意思就是说,看一看内存*reg里的值是不是oldval,如果是的话,则对其赋值newval

int compare_and_swap (int* reg, int oldval, int newval)
{
  int old_reg_val = *reg;
  if (old_reg_val == oldval) {
     *reg = newval;
  }
  return old_reg_val;
}

我们可以看到,old_reg_val 总是返回,于是,我们可以在 compare_and_swap 操作之后对其进行测试,以查看它是否与 oldval相匹配,因为它可能有所不同,这意味着另一个并发线程已成功地竞争到 compare_and_swap 并成功将 reg 值从 oldval 更改为别的值了。

这个操作可以变种为返回bool值的形式(返回 bool值的好处在于,可以调用者知道有没有更新成功):

bool compare_and_swap (int *addr, int oldval, int newval)
{
  if ( *addr != oldval ) {
      return false;
  }
  *addr = newval;
  return true;
}

与CAS相似的还有下面的原子操作:(这些东西大家自己看Wikipedia,也没什么复杂的)

注:在实际的C/C++程序中,CAS的各种实现版本如下:

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (53 人打了分,平均分: 4.21 )
Loading...
“单元测试要做多细?”

“单元测试要做多细?”

这篇文章主要来源是StackOverflow上的一个回答——“How deep are your unit tests?”。一个有13.8K的分的人(John Nolan)问了个关于TDD的问题,这个问题并不新鲜,最亮的是这个问题的Best Answer,这个问题是——

“TDD需要花时间写测试,而我们一般多少会写一些代码,而第一个测试是测试我的构造函数有没有把这个类的变量都设置对了,这会不会太过分了?那么,我们写单元测试的这个单元的粒度到底是什么样的?并且,是不是我们的测试测试得多了点?”

答案

StackOverflow上,这个问题的答案是这样的——

“I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don’t typically make a kind of mistake (like setting the wrong variables in a constructor), I don’t test for it. I do tend to make sense of test errors, so I’m extra careful when I have logic with complicated conditionals. When coding on a team, I modify my strategy to carefully test code that we, collectively, tend to get wrong.”

老板为我的代码付报酬,而不是测试,所以,我对此的价值观是——测试越少越好,少到你对你的代码质量达到了某种自信(我觉得这种的自信标准应该要高于业内的标准,当然,这种自信也可能是种自大)。如果我的编码生涯中不会犯这种典型的错误(如:在构造函数中设了个错误的值),那我就不会测试它。我倾向于去对那些有意义的错误做测试,所以,我对一些比较复杂的条件逻辑会异常地小心。当在一个团队中,我会非常小心的测试那些会让团队容易出错的代码。

这个回答对TDD似乎有一种否定,最亮的是这个问题是由Kent Beck,Kent是XP和TDD的创造者,是敏捷开发实践方法的奠基人。以致于还有人调侃到——

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (29 人打了分,平均分: 4.00 )
Loading...