Blog

栈展开(stack unwinding)

Content #

编译器会自动调用析构函数,包括在函数执行发生异常的情况。在发生异常时对析构函数的调用,还有一个专门的术语,叫栈展开(stack unwinding)。

From #

单一定义规则

Content #

C++ 会有一个单一定义的规则,该规则具体内容是什么?

如果不同的编译单元看到不同的定义的话,那链接时使用哪个定义是不确定的,结果就可能会让人吃惊。

From #

Bjarne关于C++学习的洋葱理论

Content #

抽象层次就像一个洋葱,是层层嵌套的。如果想用较低的抽象层次表达较高的概念,就好比一次切过了很多层洋葱,你会把自己的眼泪熏出来的。

与这个思路相反,教 C++ 往往有一种不好的倾向,从那些琐碎易错的底层教起,自底向上,使得学生常常在尚未领悟到抽象的真谛之前就已经被 C++ 的复杂性吓翻,从入门到放弃;或者,在学了基本的 C 语法和 class 之后就满足了,错过了高级抽象带来的全新境界。

他主张学习应当自顶向下,先学习高层的抽象,再层层剥茧、丝丝入扣地一步步进入下层。如果一次走太深的话,挫折可能就难免了。

From #

积性函数

Content #

  1. 作用在正整数范围的函数,也就是说函数 f(x) = y 中的 x 均是正整数。
  2. 如果 n 和 m 互质,那么 f(n*m) = f(n) * f(m) 。

From #

predicate in STL

Content #

Not every unary or binary function that returns a Boolean value is a valid predicate.

In addition, the STL requires that predicates be stateless, meaning that they should always yield the same result for the same value. This rules out functions that modify their internal state when they are called.

From #

function object

Content #

Since C++11, the standard uses the term function object for every object that can be used as a function call. 下面所列均可称为function object:

  1. function pointers
  2. objects of classes with operator ()
  3. objects of classes with a conversion to a point to function
  4. lambdas

C++中的function object比起普通的函数来说,有三个优点,请问是哪三个? #

1.Function objects are “functions with state.” 2.Each function object has its own type. 3.Function objects are usually faster than ordinary functions.

...

重载操作符()与lambda表达式

Content #

int id = 0;
auto f = [id] () mutable {
  std::cout << "id: " << id << std::endl;
  ++id;
};
id = 42;
f();
f();
f();
std::cout << id << std::endl;

程序输出: id: 0 id: 1 id: 2 42

改写成重载操作符():

class {
private:
  int id;
public:
  void operator() () {
    std::cout << "id: " << id << std::endl;
    ++id;
  }
};

From #

decltype

Content #

By using the new decltype keyword, you can let the compiler find out the type of an expression.

下面的C++ Template声明的函数,注意其返回值类型声明。

template <typename T1, typename T2>
    decltype(x + y) add(T1 x, T2 y);

现有如下C++声明的map:

std::map<std::string, float> coll;

用C++11的decltype关键词来声明map中的value_type变量elem:

decltype(coll)::value_type elem;

From #

remove和erase的区别

Content #

STL list中的两个成员函数remove()和erase()有何区别?

remove()成员函数可删除指定数值的元素,而erase()成员函数删除的是由iterator指定的范围。

algorithm头文件中的remove(),其参数为iterator,而iterator表示了容器的位置,但不知道具体的容器对象,因此,使用remove()是无法真正删除容器中的元素的。

容器对象的成员函数erase(),可以删除容器中的元素。

From #

递归实现生成子集算法

Content #

def subsets(S):
    if not S:
        return [[]]
    else:
        x, sub = S[0], subsets(S[1:])
        return sub + [([x] + s) for s in sub]

From #