Algorithm
Leetcode 101: https://leetcode.com/problems/symmetric-tree/
https://medium.com/@dreamume/leetcode-101-symmetric-tree-3780b21bcfdb
Review
A Note on Distributed Computing
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.7628
简介
本文发表于1994年,比较早,主要以通俗易懂的语言介绍了本地和分布式编程的区别,主要围绕本地和分布式编程无法统一这一问题展开。当时本地和分布式编程统一的观点可能比较流行。
统一对象
以前的架构如CORBA,不区分本地对象或远程对象,人们试图用统一的编程范式来编写本地和分布式代码。
然而分布式本身的特点使得统一难以实现:
- 分布式异常跟本地异常大不相同
- 分布式编程的难点在容错和缺乏集中的资源管理
本地和分布式计算
本地和分布式计算主要的不同在于延迟、内存访问、容错和并行。
延迟对分布式的影响很大。
本地计算使用相同的地址空间,而分布式导致地址空间不同。
分布式编程出现异常时情况远比本地编程复制。分布式需要考虑在部分节点异常时其他部分仍能正常工作。
分布式并行也于本地并行方式差异很大,分布式并行没有集中的资源管理、同步、错误恢复机制。
服务质量的神话
分布式编程对于服务质量的要求更加苛刻。需要考虑延迟、容错、消息去重等众多因素。分布式系统的性能也是如此。
本地和分布式系统的不同
统一本地和远程不太现实,接受本地和分布式编程的不同才是更合理的方案。
分布式编程需要使用不同于本地编程的技术。
Tips
- 多利用stl提供的接口,比如fill_n,make_move_iterator等,非常适合在一些特殊场合使用。代码简洁高效不容易出错。
Share
fererence: The C++ Programming Language
右值引用
右值引用一般指向一个临时对象,用户可能对其修改,最终会放弃使用。
好处是便于使用move操作来替代代价高昂的copy操作。
右值可以绑定到一个右值,但不能绑定左值。
string var {"Cambridge"};
string f();
string& r1 {var}; // lvalue reference, bind r1 to var (an lvalue)
string& r2 {f()}; // lvalue reference, error: f() is an rvalue
string& r3 {"Princeton"}; // lvalue reference, error: cannot bind to temporary
string&& rr1 {f()}; // rvalue reference, fine: bind rr1 to rvalue (a temporary)
string&& rr2 {var}; // rvalue reference, error: var is an lvalue
string&& rr3 {"Oxford"}; // rr3 refers to a temporary holding "Oxford"
const string cr1& {"Harvard"};// OK: make temporary and bind to cr1
右值访问跟左值或普通变量相同:
string f(string&& s) {
if (s.size())
s[0] = toupper(s[0]);
return s;
}
一些情况下,程序员知道对象不会再使用,但编译器不知道。
template<class T> swap(T& a, T& b) { // "old-style swap"
T tmp {a}; // now we have two copies of a
a = b; // now we have two copies of b
b = tmp; // now we have two copies of tmp (aka a)
}
我们可以通过声明右值来告诉编译器避免高昂的copy对象操作。
template<class T> void swap(T& a, T& b) { // "perfect swap" (almost)
T tmp {static_cast<T&&>(a)}; // the initialization may write to a
a = static_cast<T&&>(b); // the assignment may write to b
b = static_cast<T&&>(tmp); // the assignment may write to tmp
}
标志库提供了move函数替代static_cast,因此swap最终版本如下:
template<class T> void swap(T& a, T& b) { // "perfect swap" (almost)
T tmp {move(a)}; // move from a
a = move(b); // move from b
b = move(tmp); // move from tmp
}
-
引用的引用
如果定义引用的引用类型,那结果是左值引用还是右值引用呢?
using rr_i = int&&; using lr_i = int&; using rr_rr_i = rr_i&&; // ‘‘int && &&’’ is an int&& using lr_rr_i = rr_i&; // ‘‘int && &’’ is an int& using rr_lr_i = lr_i&&; // ‘‘int & &&’’ is an int& using lr_lr_i = lr_i&; // ‘‘int & &’’ is an int&
注意,左值引用总是胜出,即左值引用引用的对象类型总是左值。