至此boost一本书基本看完,很多内容粗略的扫过,大概知道了boost的能力,书中最后的总结很好,不仅指出boost的作用,同时把boost 力所不能及的地方指明,并且给了相应的解决方案。如此当遇上相同的需求时就能够快速的找到对应的解决方案。
boost 的缺点:没有达到 Java 和 Python 标准库“包罗万象”的程度:没有 GUI 库,没有 RPC 库,没有 COM+ CORBA 支持……
RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
设计模式是一个面向对象的通用解决方案,是一套被反复使用,多数人知晓的代码设计经验总结。
一般分为:创建型模式、机构型模式和行为模式
提供统一的创建接口。
将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
定义接口用于创建对象。
原型模式使用类的实例通过拷贝的方式创建对象,具体的拷贝行为可以定制。最常见的用法为类实现一个 clone() 成员函数,这个函数创建一个与原型相同或者相似的新对象。
运行时,类有且仅有一个实例。
如何组合类或者对象,更而形成更大更有用的新对象。
把一个类的接口转换成另一个接口,在不改变原有代码的基础上复用原代码。
将抽象部分与实现部分分离,使它们都可以独立的变化。
将小对象组合成树形结构。
运行时动态地给对象增加功能。
为系统中大量对象提供一个一致的对外接口,简化系统使用。
使用共享的方式节约内存的使用
它的意图不是改变接口插入新系统(适配),也不是为对象增加职责(装饰),而是要控制对象。
智能指针库,利用代理模式将原始指针包装,代理原始指针的职能。
把对象连成一条链,使链上的每个对象都有机会处理请求。
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。
给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。
备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
定义对象间一对多的联系,当一个对象的状态发生变化时,所有与它有联系的观察者对象都会得到通知。
允许对象在状态发生变化时行为也同时发生改变。
封装不同的“算法”,使它们可以在运行时相互替换。
模板方法模式准备一个抽象类,将部分逻辑以具体方法及具体构造子类的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先构建一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
分离类的内部元素和访问它们的操作,可以在不改变内部元素的情况下增加作用于它们的新操作。
用于返回无意义的对象时,它可以承担处理null的责任。
通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性。
用于为异步事件多路分离和分派处理器的对象行为模式
说了很久想去国家博物院,只是迟迟没有动脚,终于熬到今天。本不是旅游旺季,早上9点出门到那边依然能够领到票进去,排队人数也不是很多,几乎就是去了拿票直接进。如果想要预约门票的话,提早电话或者网上预定,可参见官网文章。
去的时候没有查攻略,也没有看任何文章,进到博物馆才发现那边这么大,一时间竟然不知道从那边逛起,幸而查了一眼马蜂窝,看到有人建议到地下一层从《古代中国》开始看。于是开始一段非常漫长的游览史,不是知道是因为走得太慢还是看的太认真,当走到“三国魏晋南北朝”开始已经开始寻找座位想要快速结束这段旅程了。而此后一遍又一遍的感慨中国历史太长,沉浸其中容易无法自拔。
参观的时候没有导游,所以大部分时间就是在读文物的介绍,然后自己维基百科查看,夏商周时候那些青铜器皿,几乎没有知道作用的,于是和小伙伴开始了异想天开,这是洗澡用的,这是喝酒用的,等等,不过倒也知道了一些知识:
后来的后来真的没怎么看了,几乎都是快速浏览过,就这样快速的走过,光是看了一个到1912年的《古代中国》,走出展厅就已经到了下午,后来休息了一下,又粗粗的看了书法展,国博建筑概览就匆匆过去了,很多展厅也没去看,总之以后有机会再过去看看吧。以后有了小孩,应该做好充分的准备工作再去看看,回来之后看到维基上列举的一些国家级文物,印象是有的,只是当时也没有仔细的看,四羊方尊,金缕玉衣,等等当时历史教科书中存在的图片展现到眼前是还是会激动一下的。只是后来倦于拍照片,回来整理也就只几张。
给后人的参考,其之前可以大概的浏览这个维基页面,在其中的古代中国中,列举了一些文物,有一些还是很值得一看的。比如远古时期的”人面鱼纹彩陶盆“,”玉琮“等等;夏商周的青铜器;秦汉的兵马俑,石刻;到后期的瓷器等等。
人面鱼纹彩陶盆
大禹治水图
著名的四羊方尊
金边玉杯,得此一杯,此生足矣
金制头饰,匆匆路过,突然看到这个饰品,太美了。
可爱的神兽,没想到古人也是挺萌的嘛
又一只萌萌的神兽
说不上名字的青铜器,已经忘了他叫什么了,应该也是尊吧。
最后!!!请工作人员不要这么摆设啊,会吓死人的
Boost中有两个用于并发编程的组件。首先是thead库:它为C++增加了可移植的线程处理能力。然后是一个用于同步和异步IO操作的功能强大的库——asio,它使用了前摄器模式,可以处理串口,网络通信,而且有望成为C++标准底层通信库。
互斥量是一种用于线程同步的手段,它可以在线程编程中防止多个线程同时操作共享资源(或称临界区)。一旦一个线程锁定了互斥量,那么其他线程必须等待他解锁互斥量才能在访问共享资源。thead提供了7中互斥量类型(实际只有五种):
mac下使用 boost thread 需要将 libboost_thread.dylib libboost_thread-mt.dylib lib boost-system.dylib 加入到工程,链接进工程。
具体用法:
#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
using namespace boost;
using namespace std;
#define BOOST_DATE_TIME_SOURCE
#define BOOST_THREAD_NO_LIB
// 模板类配合模板参数提供不同范围的计数,提供隐式类型转换操作
// 在多线程环境下安全计数
template <typename T>
class basic_atom: noncopyable {
private:
T n;
typedef boost::mutex mutex_t;
mutex_t mu;
public:
basic_atom(T x = T()):n(x) {}
T operator++(){
mutex_t::scoped_lock lock(mu);
return ++n;
}
// T operator=(const T _n){
// mutex_t::scoped_lock lock(mu);
// n = _n;
// return _n;
// }
operator T() {return n;}
};
boost::mutex io_mu;
typedef basic_atom<int> atom_int;
void printing(atom_int& x, const string& str){
for (int i = 0; i < 5; ++i) {
boost::mutex::scoped_lock lock(io_mu);
cout << str << ++x <<endl;
}
}
void to_interrupt(atom_int& x, const string& str){
try {
for (int i = 0; i < 5; ++i) {
this_thread::sleep(posix_time::seconds(1));
boost::mutex::scoped_lock lock(io_mu);
cout << str << ++x <<endl;
}
} catch (thread_interrupted& ) {
cout << "thread_interrupted" <<endl;
}
}
int main(int argc, const char * argv[]) {
cout << "start" <<endl;
this_thread::sleep(posix_time::seconds(2));
cout << "sleep 2 seconds" <<endl;
boost::mutex mu;
try {
mu.lock();
cout << "do some operations" << endl;
mu.unlock();
} catch (...) {
mu.unlock();
}
boost::mutex mu1;
boost::mutex::scoped_lock lock(mu1);
cout << "some operations" <<endl;
atom_int x;
thread t1(printing, boost::ref(x), "hello");
// this_thread::sleep(posix_time::seconds(2));
// join & timed_join
if (t1.joinable()) {
t1.join(); // 等待t1 线程结束再返回,不管执行多长时间
}
thread t2(printing, boost::ref(x), "boost");
t2.timed_join(posix_time::seconds(1)); // 最多等待1秒返回
thread t(to_interrupt, boost::ref(x), "interrupt");
this_thread::sleep(posix_time::seconds(4));
t.interrupt();
t.join();
return 0;
}
Boost.Asio是一个跨平台的、主要用于网络和其他一些底层输入/输出编程的C++库。以下代码实现一个简单的tcp服务,访问http://localhost:6688
可得到字符.
#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/asio.hpp>
using namespace boost;
using namespace std;
int main(int argc, const char * argv[]) {
using namespace boost::asio;
try {
io_service ios;
ip::tcp::acceptor acceptor(ios, ip::tcp::endpoint(ip::tcp::v4(), 6688));
cout << acceptor.local_endpoint().address() << endl;
while (true) {
ip::tcp::socket sock(ios);
acceptor.accept(sock);
cout << "client:" ;
cout << sock.remote_endpoint().address() << endl;
sock.write_some(buffer("hello asio"));
}
} catch (std::exception& e) {
cout << e.what() << endl;
}
return 0;
}
更多 boost.asio 相关内容查看C++ 网络编程
项目中需要将C++的程序暴露给网络使用,我也不想使用C++来用网络编程,就想到可以使用Python来解决Web端,然后将 C++ 的接口暴露给 Python 。于是在寻求解决方案的时候找到了 boost.python 库。
boost 中的 Python 库支持在 Python 和 C++ 之间的自由转换,包括 C++ 到 Python 的类型转换,默认参数,关键字参数,引用,指针等等。boost.python 库可以让 Python 轻易地调用 C++ 编写的模块,也可以很容易地在 C++ 中调用 Python 。
C++ 文件中需要包含头文件
#include <boost/python.hpp>
using namespace boost::python;
还需要在链接的时候,加入 -lboost_python
。
以下操作借助Linux下g++完成,Windows可能需要借助其他工具,导出C++函数具体实现:
hello.cpp
char const* greet()
{
return "hello, world";
}
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(hello) // Python 模块开始
{
using namespace boost::python; // 打开命名空间
def("greet", greet);
}
Makefile
PYTHON_VERSION = 2.7
PYTHON_INCLUDE = /usr/include/python$(PYTHON_VERSION)
# location of the Boost Python include files and library
#
BOOST_INC = /usr/local/include
BOOST_LIB = /usr/local/lib
# compile mesh classes
TARGET = hello
$(TARGET).so: $(TARGET).o
g++ -shared $(TARGET).o -L$(BOOST_LIB) -lboost_python -L/usr/lib/python$(PYTHON_VERSION)/config -lpython$(PYTHON_VERSION) -o $(TARGET).so
$(TARGET).o: $(TARGET).cpp
g++ -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -fPIC -c $(TARGET).cpp
clean:
rm *.so *.o
hello.py
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import hello
print hello.greet()
输出: hello, world
注意将 python, boost 所在目录 include 进去,在链接时加上 -lboost_python -lpython2.7
并 include python 和 boost目录。
Demo 地址GitLab : https://gitlab.com/einverne/boost_test/
这两天陆陆续续通过一些插件脚本删除了一些社交网站数据。年轻的时候发过一些无聊的状态,然后很久以后都没有登陆过的一些账号,倒不如关了的好,自此以后墙外只用 Google+ , 还有 Blog 记录一下所思所想,墙内公开内容除了豆瓣可能也没得发了,不愿生活在一个审查的制度下。虽然我可能也不会发什么敏感的内容,可谁知道什么敏感,什么不敏感呢?
Delete all facebook posts , 可以利用以下插件删除 Facebook 所有状态,包括账号内的头像等等。
Chrome Extension link
https://chrome.google.com/webstore/detail/facebook-timeline-cleaner/lfejocdlmhhkmnabbaeckmaehmgaffje
Update: 可惜了这个插件被删除了
关闭账号
delete tool 删除工具 http://app.weibo.com/detail/62A7lB
批量删除 weibo http://3.amfen.sinaapp.com/
删除微博评论 http://weibo333.com/
设置中关闭账号
通过以下链接申请删除 QQ 空间。
间谍之桥 Bridge of Spies 2015 影评
一名伟大的律师,成就一件伟大的人质交换。剧情7分,表演8分,娱乐7分。汤姆汉克斯的演技自然没得说,不过俄国人质的更加深入人心,虽然并不知道他的名字,但之后就再不会忘记他的名字 —- Mark Rylance 。而电影在娱乐性方面给人更多的是思考,沉浸在那段历史中,思考的是那段历史中人们做过的每一个决策。
原本以为这部影片是讲述“间谍”之间的故事,看到开场辩护时就知道被标题所骗。联系到最近的快播案,两国在司法上可谓天上地下。从1957年的《十二怒汉》开始,到这部《间谍之桥》50多年间好莱坞从未放弃探讨司法的公平性。而前半部分的辩护差点让我以为电影会从间谍故事转变成法庭辩护。幸而在后面美国侦察机被炸到苏联土地等情节,才让故事走上交换人质的主线。也让电影变得更加主旋律。
电影中最棒的两段台词:
第一段出现在CIA希望Donovan背弃律师的誓言泄露被告的信息时,Donovan告诉CIA探员的话:
I’m Irish, you’re German, but what makes us both Americans? Just one thing, one one one. The rule book. We call it the Constitution. We agree to the rules, and that’s what makes us Americans, it’s all that makes us Americans.
第二段是 Donovan和 Abel 之间的对话。
DONOVAN: You don’t seem alarmed. ABEL: Would it help?
电影剧本下载地址
su 用来切换身份或者升级成使用 superuser。如果没有加任何参数,则 su 默认变为 superuser。
su [options] [username]
su 命令用来改变当前登录 session 的用户身份。直接使用 su
默认成为 superuser,使用参数 su -
短横线,则完全切换成该用户登录的状态,连同环境变量一同切换,工作目录也会切换。
-c 指令 或 --command= 指令 :执行完指定的指令后,即恢复原来的身份;
-f 或——fast:适用于 csh 与 tsch,使 shell 不用去读取启动文件;
- 或 -l 或——login:改变身份时,也同时变更工作目录,以及 HOME,SHELL,USER,logname。此外,也会变更 PATH 变量;
-m,-p 或 --preserve-environment:变更身份时,不要变更环境变量;
-s 或 --shell=:指定要执行的 shell;
切换用户而不切换工作目录
whoami # 显示当前用户
einverne
pwd # 当前目录
/home/einverne
su root # 切换到 root 用户
Password:
ev einverne # whoami
root
ev einverne # pwd
/home/einverne
ev einverne # exit
exit
切换用户并切换工作目录
whoami
einverne
pwd
/home/einverne
su -
Password:
ev ~ # pwd # 注意此目录
/root
ev ~ #
对应书中第8章 算法,这一章作者介绍的很简单,只是举例使用 foreach , minmax ,其他算法都略去了。
将C++的语法扩充,使用 foreach 循环变量。
需包含头文件
#include <boost/foreach_hpp>
具体用法:
#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
using namespace boost;
using namespace std;
int main(int argc, const char * argv[]) {
using namespace boost::assign;
vector<int> v = (list_of<int>(1),2,3,4,5);
/**
* 第一个参数 VAR 是循环变量声明 想要高效地使用序列内元素或者修改序列,需要声明使用引用
* 第二个参数 COL 是要遍历的序列
*
*/
BOOST_FOREACH(int x, v){
cout << x << "-";
}
cout << endl;
string str("hello world");
BOOST_FOREACH(char& c, str){
cout << c << "-";
}
cout << endl;
// use typeof
BOOST_TYPEOF(*v.begin()) y; // BOOST_AUTO(y, *v.begin())
BOOST_FOREACH(y, v){
cout << y << ",";
}
cout << endl;
return 0;
}
在同一次操作中同时获取最大最小值。需包含头文件:
#include <boost/algorithm/minmax.hpp>
using namespace boost;
具体用法:
#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/algorithm/minmax_element.hpp>
using namespace boost;
using namespace std;
int main(int argc, const char * argv[]) {
using namespace boost::assign;
vector<int> v = (list_of(543), 90, 23, 42, 3, 10);
BOOST_AUTO(x ,boost::minmax_element(v.begin(), v.end()));
cout << "min: " << *x.first << endl;
cout << "max: " << *x.second << endl;
// first_min_element 找到第一个最小值
// last_min_element 最后一个最小值
return 0;
}
上一篇文章boost容器中留下一个property_tree
没有学,觉得既然 boost 提供了 property_tree 这样好的工具来给C++ 解析xml和Json,必须要留有一定的篇幅来讲它。
原先项目中使用到JSON,需要使用C++解析一段返回值, JSON 格式如下:
{
"ret": "101",
"error": [
{
"errortype": "A0001",
"errorstroke": {
"0": "0.2",
"1": "0.3"
}
},
{
"errortype": "A0021",
"errorstroke": {
"0": "0.2",
"1": "0.3"
}
}
]
}
error 字段是一个数组,数组中的每个元素都是一个对象Object,每个Object中是一个键值对,其中 errorstroke 同样包含一个对象。我们都知道JSON只包含三种数据结构,矢量,数组和映射(参考),这样无疑给我们的解析工作带来很多遍历,这三种数据结构几乎可以将时间所有的信息包含进去。
下面就是解析这段 JSON 字符串的具体代码:(注意将JSON字符串 escape)
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>
using namespace boost::property_tree;
int main(int argc, const char * argv[]) {
std::string str_json = "{\"ret\":\"101\",\"error\":[{\"errortype\":\"A0001\",\"errorstroke\":{\"0\":\"0.2\",\"1\":\"0.3\"}},{\"errortype\":\"A0021\",\"errorstroke\":{\"0\":\"0.2\",\"1\":\"0.3\"}}]}";
ptree pt; //define property_tree object
std::stringstream ss(str_json);
try {
read_json(ss, pt); //parse json
} catch (ptree_error & e) {
return 1;
}
std::cout << pt.get<std::string>("ret") << std::endl;
ptree errortype = pt.get_child("error"); // get_child to get errors
// first way
for (boost::property_tree::ptree::iterator it = errortype.begin(); it != errortype.end(); ++it) {
std::cout << it->first;
std::cout << it->second.get<std::string>("errortype") << std::endl;
ptree errorstroke = it->second.get_child("errorstroke");
for (ptree::iterator iter = errorstroke.begin(); iter != errorstroke.end(); ++iter) {
std::string key = iter->first;
std::cout << iter->first << std::endl;
std::cout << iter->second.data() << std::endl;
}
}
// second way: using boost foreach feature
// BOOST_FOREACH(ptree::value_type &v, errortype){
// ptree& childparse = v.second;
// std::cout << childparse.get<std::string>("errortype") << std::endl;
// ptree errorstroke = childparse.get_child("errorstroke");
// BOOST_FOREACH(ptree::value_type& w, errorstroke){
// std::cout << w.first << std::endl;
// std::cout << w.second.data() << std::endl;
// }
// }
return 0;
}
代码的输出:
101
A0001
0
0.2
1
0.3
A0021
0
0.2
1
0.3
再换用另外一段 JSON 尝试解析,从下面这段 JSON 中能够轻易的看出 JSON 内部的结构,支持的数据结构和类型:
{
"array": [
1,
2,
3
],
"boolean": true,
"null": null,
"number": 123,
"object": {
"a": "b",
"c": "d",
"e": "f"
},
"string": "Hello World"
}
具体解析代码:
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>
using namespace std;
using namespace boost::property_tree;
int main(int argc, const char * argv[]) {
std::string str_json = "{\"array\":[1,2,3],\"boolean\":true,\"null\":null,\"number\":123,\"object\":{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},\"string\":\"Hello World\"}";
ptree pt; //define property_tree object
std::stringstream ss(str_json);
try {
read_json(ss, pt); //parse json
} catch (ptree_error & e) {
return 1;
}
ptree arraypt =pt.get_child("array");
for (boost::property_tree::ptree::iterator it = arraypt.begin(); it != arraypt.end(); ++it) {
cout << it->second.data() << " ";
}
cout << endl;
std::cout << pt.get<bool>("boolean") << std::endl;
std::cout << pt.get<std::string>("null") << std::endl;
std::cout << pt.get<int>("number") << std::endl;
std::cout << pt.get<std::string>("string") << std::endl;
ptree opt = pt.get_child("object");
BOOST_FOREACH(ptree::value_type &v, opt){
cout << v.first << " : ";
cout << v.second.data() << endl;
}
return 0;
}
利用 Boost property_tree 构造 JSON 字串,以下代码能够构造上面的JSON:
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>
using namespace std;
using namespace boost::property_tree;
int main(int argc, const char * argv[]) {
std::string str_json = "{\"array\":[1,2,3],\"boolean\":true,\"null\":null,\"number\":123,\"object\":{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},\"string\":\"Hello World\"}";
ptree root, arr,object;
arr.push_back(std::make_pair("","1"));
arr.push_back(std::make_pair("","2"));
arr.push_back(std::make_pair("","3"));
object.put("a","b");
object.put("c","d");
object.put("e","f");
root.add_child("array", arr);
bool boolvalue = true;
root.put("boolean",boolvalue);
root.put("null","null");
int num = 123;
root.put("number",num);
root.add_child("object",object);
root.put("string","Hello World");
//write_json("out.json", root);
stringstream s;
write_json(s, root, false);
string out = s.str();
cout << out ;
return 0;
}
两个有用的JSON工具:
Boost property_tree 解析 XML 可参考这篇文章 ,解释得非常清楚。