撸汇编学习

汇编一直是弱项, 于是搞了一会浅薄的内容. 做个笔记. void foo() { int a, b, c, d; } int main() { foo(); int a=10; } 这里的流程是: main(): 把 rsp 赋值给 rbp 把 rsp – 10(或者某个数). 此时: rbp –> | | | rsp –> | 调用 foo rbp(main)–>| | | rsp/rbp –>| 初始化 a 到 d: rbp(main)–>| main | | rsp/rbp –>| […]

rand 相关

gcc 的 rand 使用 http://en.wikipedia.org/wiki/Linear_congruential_generator 生成随机数. 从 http://cpp.indi.frih.net/blog/2014/12/the-bell-has-tolled-for-rand/ 看, time() 作为种子, 因为 time_t 最小单位是一秒, 所以一秒内跑两次程序会得到同样的结果. 验证发现确实如此… 现在的标准推荐使用 http://en.wikipedia.org/wiki/Mersenne_twister, 好多语言在用它做默认生成器. 另应该记住 VS 的 rand_max 只有 32767, 所以 rand 范围只有 32768, 这点可以用来吐槽 MS, 真是太棒了

is_container 和 add 的修改版

使用boost库对is_container的修改 利用现有boost库,对owensss实现的is_container等设施做一些更新,使代码更简洁 has_xxx.hpp #ifdef TNAME #include <type_traits> #include <boost/preprocessor/cat.hpp> template <class T> struct BOOST_PP_CAT(has_, TNAME) { template <class> static constexpr bool test(…) { return false; } template <class U> static constexpr bool test(std::remove_reference_t<typename U::TNAME>*) { return true; } static constexpr bool value = test<T>(nullptr); using type = ::bool_<value>; }; template <class T> constexpr bool BOOST_PP_CAT(BOOST_PP_CAT(has_, […]

一个 通用的 add 设施 以及 is_container

写了一个通用的 add 设施, 原型如下: add(container_output, container_input) // 重载 1 效果: 把 container_input 里的所有元素加到(push_back) container_output 里 add(container_output, elements…) // 重载 2 效果: 把所有 elements 加到(push_back) container_output 里 实现上, 使用 enable_if 做函数决议. 为此写了一个 is_container 设施判断类型是否是 container. 该设施部分遵循 Container Concept 的定义. 主要是构造啊 swap 啊几个操作符啊查起来太麻烦了. 所以没加. 首先是 is_container 的实现: pp_cat.h, 做字符拼接. #ifndef BOOST_PP_CAT # define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b) […]

new 在 lambda

看到一个问题,如何把 lambda 弄到 new 出来的地址上。 一开始的想法是:lambda 在声明的时候就已经是 rv 了,而 trivial move ctor 是 优先 move 的 bitwise copy,那肯定搞不定啊。 举例说: something = move([]{}); // 此时,某个匿名函数已经构造完毕,所以 这里的实际代码是: something.m_a = move(__unnamed.m_a); something.m_b = move(__unnamed.m_b); … 等于白搭。 但两次询问问题人后其确定 void* p = (void*) new sometype([]{}); 的语法是能够把 lambda 的构造弄到 new 出来的内存上的。于是开干吧。 首先查阅 gcc 源码,得知其 lambda 命名规则是 __lambda%d,%d 跟第 lambdacnt 个。所以 第 […]

优雅地同时遍历多个容器

问:给定容器 C1, C2, C3, … Cn, 且已知 size(C1) == size(C2) == … == size(Cn); 如何优雅地 for (c1, c2, c3… cn) in (C1, C2, C3, … Cn): // do something 意义:可能会有两个同样大小的变长容器(vector 啊 list 啊 map 啊 blabla),确认是同样大小了,希望对其中索引相同的元素做某些事情,这种需求不属于最常见的一类,但属于一般都会遇到的一类。 答: 为了直观感受 “不优雅”, “丑陋的”,展示一下现有条件下可能的实现: C1_T::iterator iter1 = C1.begin(); C2_T::iterator iter2 = C2.begin(); … Cn_T::iterator itern = Cn.begin(); for (; […]

瞎搞 std::cout 的构造和析构顺序

本文使用 gcc4.8, libstdc++. 引入 昨天侃爷提了个问题: struct foo { foo(const std::string& c) :_c(c) {} ~foo() { std::cout << _c; } const string& _c; } bar(“aaa”) ; 会炸, 为什么呢. 因为 “aaa” 会被赋予一个临时的 string, 然后这个临时 string 在程序结束的时候早挂了, 所以会 sf. 可是, 有没有可能是 cout 先被析构, 导致整个程序挂掉? 讨论 理论上, cout 应该是早于 bar 被声明的(extern), 所以它析构的也会比 bar 晚. 肚学长提出编译器在生成可执行文件的时候做了特殊处理, 我觉得 运行库 和 标准库 […]

scope_exit 的 11 实现

#ifndef SCOPE_EXIT_HPP #define SCOPE_EXIT_HPP #include “pp_cat.h” #include <functional> #define SCOPE_EXIT_CLASSNAME(id) PP_CAT(__unique_classname__, id) #define SCOPE_EXIT_INSTANCENAME(id) PP_CAT(__unique_instance__, id) #define SCOPE_EXIT(…) struct SCOPE_EXIT_CLASSNAME(__LINE__) { typedef std::function<void(void)> fun; fun f_; SCOPE_EXIT_CLASSNAME(__LINE__) (fun f) :f_(f) { } ~SCOPE_EXIT_CLASSNAME(__LINE__) () { f_(); } } SCOPE_EXIT_INSTANCENAME(__LINE__) ([__VA_ARGS__]() #define SCOPE_EXIT_END ); #endif // SCOPE_EXIT_HPP 设计思路见 boost. 主要的方法是利用 析构函数, 在退出 scope 时自动执行代码. 1. 为了使 […]

scanf 相关

好像集训队的学长们对这个都很熟. 我啥都不懂在乱用土死了. 集合匹配用 [] 逆向匹配用 [^] 比方 scanf(“%[ab,]”, str); // 1 scanf(“%[^;]”,str); // 2 1 匹配 所有ab和逗号.  “aabbb,ab,aaacasdsdef” 2. 匹配除了分号外的所有字符 “aaa;bbbbccc” 表示匹配但不赋值. scanf(“%[ab,]”); 然后 http://en.cppreference.com/w/cpp/types/integer 用法 “%” SCNd64 比如. 貌似是 C99 的标准…看了下源码其实就是各种平台相关 define… 嗯差不多就这样 简直太土了…

libcxx 的 shared_ptr 实现分析

##以 libcxx 为对象的 shared_ptr 实现分析。## 注意:gcc 用的是 libstdc++ , 这里的 libcxx 是 llvm 的项目. 两者的 shared_ptr 实现相似但不相同 一个 shared_ptr/weak_ptr 存放两个指针,一个是被 manage 的 Tp* ptr, 一个是管理块, cntrl. 所以一个 shared_ptr/weak_ptr 的 空间开销 = 2*sizeof pointer。待会再说 cntrl 的空间开销。 访问 ptr 的时间开销是 1,没有性能损失。 ptr 没什么好说,每一个 shared_ptr/weak_ptr 存一份。那么 cntrl 呢? 首先说 cntrl 干什么。 cntrl 块存 shared_count weak_count allocator deleter ptr […]