<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>G++ on I'm OWenT</title><link>//owent.net/tags/g++.html</link><description>Recent content in G++ on I'm OWenT</description><generator>Hugo</generator><language>zh-cn</language><copyright>&lt;a rel="license" href="https://github.com/owent/blog-hugo/blob/master/LICENSE.md"&gt;&lt;img alt="知识共享许可协议" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/80x15.png" /&gt;&lt;/a&gt;</copyright><lastBuildDate>Sat, 01 Jul 2017 15:57:29 +0000</lastBuildDate><atom:link href="//owent.net/tags/g++/index.xml" rel="self" type="application/rss+xml"/><item><title>libcopp v2的第一波优化完成</title><link>//owent.net/2017/1466.html</link><pubDate>Sat, 01 Jul 2017 15:57:29 +0000</pubDate><guid>//owent.net/2017/1466.html</guid><description>&lt;p&gt;之前测出来&lt;a href="https://github.com/owent/libcopp"&gt;libcopp&lt;/a&gt;还有一些列优化点，但是要破坏之前的API，所以整理了一下优化的想法和方案。&lt;/p&gt;&#10;&lt;h2 id="预留空间和合并分配"&gt;预留空间和合并分配&lt;/h2&gt;&#10;&lt;p&gt;之前有太多的堆内存分配了，导致很多碎片。那么第一个想法就是协程对象可以分配在栈上，runner也可以分配在栈上。然后还可以加一个自定义预留长度。每个对象对齐到sizeof(long)，总长度对齐到64 Bytes。&lt;/p&gt;</description></item><item><title>libcopp(v2) vs goroutine性能测试</title><link>//owent.net/2017/1465.html</link><pubDate>Sat, 10 Jun 2017 15:57:29 +0000</pubDate><guid>//owent.net/2017/1465.html</guid><description>&lt;p&gt;本来是没想写这个对比。无奈之前和&lt;a href="https://github.com/yuanzhubi/call_in_stack"&gt;call_in_stack&lt;/a&gt;的作者聊了一阵，发现了一些&lt;a href="https://github.com/owent/libcopp"&gt;libcopp&lt;/a&gt;的改进空间。然后顺便看了新的boost.context的cc部分的代码，有所启发。想给&lt;a href="https://github.com/owent/libcopp"&gt;libcopp&lt;/a&gt;做一些优化，主要集中在减少分配次数从而减少内存碎片；在支持的编译器里有些地方用右值引用来减少不必要的拷贝；减少原子操作和减少L1cache miss几个方面。&lt;/p&gt;&#10;&lt;p&gt;之后改造了茫茫多流程和接口后出了v2版本，虽然没完全优化完，但是组织结构已经定型了，可以用来做压力测试。为了以后方便顺便还把cppcheck和clang-analyzer的静态分析工具写进了dev脚本。然后万万没想到的是，在大量协程的情况下，benchmark的结果性能居然比原来还下降了大约1/3。&lt;/p&gt;</description></item><item><title>libcopp的线程安全、栈池和merge boost.context 1.64.0</title><link>//owent.net/2017/1446.html</link><pubDate>Fri, 12 May 2017 19:45:17 +0000</pubDate><guid>//owent.net/2017/1446.html</guid><description>&lt;!-- toc --&gt;&#13;&#10;&lt;h2 id="线程安全"&gt;线程安全&lt;/h2&gt;&#10;&lt;p&gt;前段时间看到了一个完成读比较高的协程库-&lt;a href="https://github.com/yyzybb537/libgo"&gt;libgo&lt;/a&gt;，里面提供了线程安全的协程实现，并且也是使用锁。本来我并没有给&lt;a href="https://github.com/owent/libcopp"&gt;libcopp&lt;/a&gt;里的功能加锁的打算，因为上层dispatcher还是比较容易做到安全分发的，所以原来并不保证线程安全。而且线程安全这种问题单元测试比较难写，可能还得碰点运气。但是思来想去，还是为线程安全做点什么吧。反正也不是很复杂。&lt;/p&gt;&#10;&lt;p&gt;由于我并没有给utils加互斥锁的跨平台适配，所以先就直接用了自旋锁，来锁住需要考虑线程安全的地方。其实需要加锁的地方并不多，无非是管理器的增删查和task的next函数需要加锁。这些逻辑都很短，功能也很简单，并不会占用太多时间，所以自旋锁的问题也不大。而且以后真发现有问题，换掉也不是什么难事儿。&lt;/p&gt;</description></item><item><title>GCC 7和LLVM+Clang+libc++abi 4.0的构建脚本</title><link>//owent.net/2017/1431.html</link><pubDate>Tue, 09 May 2017 11:17:55 +0000</pubDate><guid>//owent.net/2017/1431.html</guid><description>&lt;p&gt;之前的版本发完，有空来更新一下之前的gcc和llvm+clang工具链的编译脚本了。其实GCC 7是才release没多久但是llvm 4.0发布其实有一段时间了。&lt;/p&gt;&#10;&lt;h2 id="gcc"&gt;GCC&lt;/h2&gt;&#10;&lt;p&gt;这回是GCC的脚本有一些改动。因为我现在开发机的环境很多组件并没有装，所以顺带发现了之前的构建脚本的一些问题。&lt;/p&gt;</description></item><item><title>libatbus的几个藏得很深的bug</title><link>//owent.net/2017/1411.html</link><pubDate>Sun, 23 Apr 2017 23:48:54 +0000</pubDate><guid>//owent.net/2017/1411.html</guid><description>&lt;!-- toc --&gt;&#13;&#10;&lt;p&gt;在写这篇文章前，我突然想到以前流行了一段时间的服务器面试题：当一个BUG只有几百万分之一的概率会出现，怎么办？这个问题在这个BUG里只是毛毛雨而已，因为这次的BUG的&lt;strong&gt;出现概率是夸张的三亿分之一&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;我在好几年前自己开发了一个用于服务器进程间通信的框架，&lt;a href="https://github.com/atframework/libatbus"&gt;libatbus&lt;/a&gt;，以前用在了客户端的模块隔离的通信心痛中。并且现在开始正式用于服务器。但是前两天看了一下服务器的日志，发现了比较奇怪的-202错误。&lt;/p&gt;</description></item><item><title>atsf4g完整游戏工程示例</title><link>//owent.net/2016/1306.html</link><pubDate>Sun, 23 Oct 2016 12:31:14 +0000</pubDate><guid>//owent.net/2016/1306.html</guid><description>&lt;!-- toc --&gt;&#13;&#10;&lt;p&gt;近期仍然在搭建完整的游戏服务器架构。基于&lt;a href="https://github.com/atframework/atsf4g-co/"&gt;atsf4g（asynchronously-tree server framework fo game）&lt;/a&gt;的完整解决方案终于接近完成。基本框架之前其实已经做完了，但是之前解决的只是基本的框架层代码，不包含任何特定的交互模型、协议模型、配置服务等等。这回就整理了一个只包含登入登出逻辑的完整工程，另外优化了一些小细节和周边工具的支持。&lt;/p&gt;</description></item><item><title>atframework基本框架已经完成</title><link>//owent.net/2016/1301.html</link><pubDate>Thu, 22 Sep 2016 17:10:11 +0000</pubDate><guid>//owent.net/2016/1301.html</guid><description>&lt;p&gt;好久没写blog了。最近空闲时间都在加紧完成&lt;a href="https://atframe.work"&gt;atframework&lt;/a&gt;框架。总算是搞完了，并且搭建了一个静态介绍页。以后有空慢慢加文档进去。&lt;/p&gt;&#10;&lt;p&gt;主页: &lt;a href="https://atframe.work/"&gt;https://atframe.work/&lt;/a&gt;&#10;Github: &lt;a href="https://github.com/atframework/"&gt;https://github.com/atframework/&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;目前这个项目已经是一个小型游戏服务器的完整框架，包括服务器间实例的管理、客户端和服务器的内部协议和通信机制。并且实现了纯C的port。&#10;然后&lt;a href="https://github.com/atframework/atsf4g-co/tree/master/sample/atgw_cli_inner_hello"&gt;https://github.com/atframework/atsf4g-co/tree/master/sample/atgw_cli_inner_hello&lt;/a&gt;里提供了c++的客户度端的代码示例，&lt;a href="https://github.com/atframework/AtgwInnerCli-CSharp"&gt;https://github.com/atframework/AtgwInnerCli-CSharp&lt;/a&gt;里提供了C#的客户端代码示例。&#10;使用的都是同一个纯C的协议porting。这样无论cocos还是unity框架接入都不困难了。其他的框架也可以直接用这个纯C的porting来接入。&lt;/p&gt;</description></item><item><title>游戏服务器的不停服更新</title><link>//owent.net/2016/1294.html</link><pubDate>Sun, 31 Jul 2016 17:23:34 +0000</pubDate><guid>//owent.net/2016/1294.html</guid><description>&lt;p&gt;我们目前的游戏第一次测试的时候笔记送匆忙，导致上线之后频繁更新。&#10;比如BOSS战由于大区的人数和预期不一样导致的难度调整，或者是任务链或者数值调整，再加上一些BUG。&lt;/p&gt;&#10;&lt;p&gt;但是每次停服更新的话用户体验是比较伤的，所以后来就采取了一些措施来减少更新的停服时间。最后基本实现了不停服更新。&lt;/p&gt;</description></item><item><title>Android和IOS的TLS问题</title><link>//owent.net/2016/1285.html</link><pubDate>Sat, 09 Jul 2016 14:15:14 +0000</pubDate><guid>//owent.net/2016/1285.html</guid><description>&lt;p&gt;这个问题起源于以前给客户端写的一个log模块，然后里面为了线程安全且多线程下不互相写乱，并且因为这些系统基本都用比较高版本的编译器，都支持C++11了，所以就用了C++11的TLS功能。&lt;/p&gt;&#10;&lt;p&gt;但是Android的默认std库并不是libstdc++或者libc++，而是&lt;a href="http://en.wikipedia.org/wiki/Bionic_%28software%29#cite_note-Gentry-6"&gt;Bionic&lt;/a&gt;。IOS不知道是什么版本的标准库都不支持thread_local的关键字。&#10;这个之前写过一个记录提到过 &lt;a href="https://www.owent.net/2015/1140.html"&gt;Android NDK undefined reference to ___tls_get_addr 错误&lt;/a&gt;。如果使用这个关键字，链接的时候会报错说找不到符号。&lt;/p&gt;</description></item><item><title>boost.context-1.61版本的设计模型变化</title><link>//owent.net/2016/1270.html</link><pubDate>Tue, 14 Jun 2016 17:40:29 +0000</pubDate><guid>//owent.net/2016/1270.html</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;&#10;&lt;p&gt;之前写了个C++的协程框架&lt;a href="https://github.com/owent/libcopp"&gt;libcopp&lt;/a&gt;，底层使用的是boost.context实现，然后剥离了对boost的依赖。然而这样意味着我必须时常跟进&lt;a href="http://www.boost.org/doc/libs/1_61_0/libs/context/doc/html/index.html"&gt;boost.context&lt;/a&gt;的更新。&lt;/p&gt;&#10;&lt;p&gt;顺带提一下这个协程库已经在我们线上服务器版本中使用了。&lt;/p&gt;&#10;&lt;p&gt;从最初的boost版本（我忘了从哪个版本开始了）一直到1.60版本，&lt;a href="http://www.boost.org/doc/libs/1_61_0/libs/context/doc/html/index.html"&gt;boost.context&lt;/a&gt;的变化都不大，都只是补全一些新的架构和体系结构，还有就是修复一些小细节的BUG，再就是增加了对valgrind的支持（之前写过一个&lt;a href="//owent.net/2015/1194.html"&gt;Merge记录&lt;/a&gt;提到过）。新增的功能也只有&lt;a href="http://www.boost.org/doc/libs/1_61_0/libs/context/doc/html/context/ecv1.html"&gt;execution_context&lt;/a&gt;(现在叫execution_context_v1)，这个东西我的&lt;a href="https://github.com/owent/libcopp"&gt;libcopp&lt;/a&gt;里其实包含了这个功能，并且本身做得比它要功能丰富，所以没有接入的必要。另外在1.60版本的时候尝试使用Windows里的fiber（当然默认是关闭的），在1.61版本里被移除了。这些细节都不是特别重要，主要还是1.61版本的变化。&lt;/p&gt;&#10;&lt;p&gt;然而这次变化就比较大了，首先所有的API都变更了，汇编代码里的参数和返回值也都发生了变化，当然语义也不一样了，另外还增加了新的API&lt;strong&gt;ontop_fcontext&lt;/strong&gt;。这些变化使得&lt;a href="https://github.com/owent/libcopp"&gt;libcopp&lt;/a&gt;的逻辑关系也必须有一些相应的调整，为了理清思路，这些都在后面分析。&lt;/p&gt;</description></item><item><title>libatbus基本功能及单元测试终于写完啦</title><link>//owent.net/2016/1214.html</link><pubDate>Fri, 19 Feb 2016 12:44:53 +0000</pubDate><guid>//owent.net/2016/1214.html</guid><description>&lt;h2 id="libatbus"&gt;&lt;a href="https://github.com/atframework/libatbus"&gt;libatbus&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;经过茫茫长时间的编写+过年在家无聊补充和修正单元测试，再加上这两天的整理，终于把以前的这个关于服务器通信中间件的基本功能和相应的单元测试完成啦。还是可以热烈庆祝一下的。&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://www.owent.net/2014/1090.html"&gt;《关于BUS通信系统的一些思考（一）》&lt;/a&gt;&#10;&lt;a href="https://www.owent.net/2014/1099.html"&gt;《关于BUS通信系统的一些思考（二）》&lt;/a&gt;&#10;&lt;a href="https://www.owent.net/2015/1201.html"&gt;《关于BUS通信系统的一些思考（三）》&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;主要的思路还是在自动选择&lt;strong&gt;共享内存&lt;/strong&gt;或是&lt;strong&gt;tcp&lt;/strong&gt;或是&lt;strong&gt;unix socket&lt;/strong&gt;进行通信。使用节点ID，屏蔽底层通信细节，屏蔽自动重连细节和节点之间自动建立直连的细节。同时基于目前的游戏服务器架构设计方式预留了一些拓展性的设计，以便于后续服务器框架的实现。主要是指全异步，树形结构，自动化的容灾设计和动态扩容缩容，不停服更新，统计等等。&lt;/p&gt;</description></item><item><title>小记最近踩得两个C++坑</title><link>//owent.net/2015/1189.html</link><pubDate>Sat, 25 Jul 2015 14:53:44 +0000</pubDate><guid>//owent.net/2015/1189.html</guid><description>&lt;h1 id="小记最近踩得两个c坑"&gt;小记最近踩得两个C++坑&lt;/h1&gt;&#10;&lt;!-- toc --&gt;&#13;&#10;&lt;p&gt;记一下最近踩得两个C++独有的暗坑，其中一个和ABI相关。第二个坑其实之前研究过，但是没有实例，这次算是碰到了个典型的实例。&lt;/p&gt;&#10;&lt;h2 id="坑一常量引用失效"&gt;坑一：常量引用失效&lt;/h2&gt;&#10;&lt;p&gt;在项目中碰到的实例的大致流程是:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;获取某个容易的迭代器，迭代器内包含智能指针（std::shared_ptr）&lt;/li&gt;&#10;&lt;li&gt;把智能指针通过常量引用方式传入函数&lt;/li&gt;&#10;&lt;li&gt;执行过程中智能指针被释放&lt;/li&gt;&#10;&lt;li&gt;于是这时候，我们有了一个空悬的智能指针引用了&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;用代码表示的话，流程如下:&lt;/p&gt;</description></item><item><title>Android NDK undefined reference to ___tls_get_addr 错误</title><link>//owent.net/2015/1140.html</link><pubDate>Fri, 06 Feb 2015 20:27:16 +0000</pubDate><guid>//owent.net/2015/1140.html</guid><description>&lt;p&gt;本来看到Android的ndk都开始用gcc4.8和gcc4.9了，而且gcc4.8.1开始支持全部的c++11的特性，我就很happy地用上了。结果出现这么个错误。&lt;/p&gt;&#10;&lt;p&gt;网上查到说是Android的run time竟然不支持&lt;a href="http://en.cppreference.com/w/cpp/language/storage_duration"&gt; thread local storage（TLS）&lt;/a&gt;，更准确地说，是它没实现。&lt;/p&gt;</description></item><item><title>LLVM + Clang + Libcxx + Libcxxabi 工具链编译</title><link>//owent.net/2014/1101.html</link><pubDate>Fri, 12 Sep 2014 19:07:03 +0000</pubDate><guid>//owent.net/2014/1101.html</guid><description>&lt;p&gt;LLVM和Clang工具链的生成配置文件写得比较搓，所以略微麻烦，另外这个脚本没有经过多环境测试，不保证在其他Linux发行版里正常使用。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;如果第一次执行出现安装失败，可以再执行一次。llvm的安装脚本问题多多&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>[libiniloader] Project</title><link>//owent.net/2014/1081.html</link><pubDate>Mon, 14 Jul 2014 19:28:49 +0000</pubDate><guid>//owent.net/2014/1081.html</guid><description>&lt;h2 id="ini-配置读取库发布"&gt;INI 配置读取库发布&lt;/h2&gt;&#10;&lt;p&gt;Github地址: &lt;a href="https://github.com/owent/libiniloader"&gt;https://github.com/owent/libiniloader&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;OSChina镜像: &lt;a href="http://git.oschina.net/owent/libiniloader"&gt;http://git.oschina.net/owent/libiniloader&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;项目中经常会碰到需要读取配置的情况，而用ini配置最大的优势就是简单易懂。&#10;但是现在很多的配置读取库都过于庞大了，比如Boost.PropertyTree，功能很强大，但是基本不会用到里面所有的东西。&#10;另外微软的INI读取，功能不是很强不说，还限制在Windows上，更重要的是API设计得实在不优雅。&#10;于是libiniloader就诞生啦。&lt;/p&gt;</description></item><item><title>再议 C++ 11 Lambda表达式</title><link>//owent.net/2014/1060.html</link><pubDate>Tue, 03 Jun 2014 20:55:44 +0000</pubDate><guid>//owent.net/2014/1060.html</guid><description>&lt;h2 id="目录"&gt;目录&lt;/h2&gt;&#10;&lt;!-- toc --&gt;&#13;&#10;&lt;h2 id="c-的lambda表达式"&gt;C++ 的Lambda表达式&lt;/h2&gt;&#10;&lt;p&gt;C++ 11 标准发布，各大编译器都开始支持里面的各种新特性，其中一项比较有意思的就是lambda表达式。&lt;/p&gt;&#10;&lt;h2 id="语法规则"&gt;语法规则&lt;/h2&gt;&#10;&lt;p&gt;C++ 11 Lambda表达式的四种声明方式&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&#10;\[ capture \]( params ) mutable(optional) exception attribute -&amp;gt; ret { body }&lt;/li&gt;&#10;&lt;li&gt;&#10;\[ capture \]( params ) -&amp;gt; ret { body }&lt;/li&gt;&#10;&lt;li&gt;&#10;\[ capture \]( params ) { body }&lt;/li&gt;&#10;&lt;li&gt;&#10;\[ capture \]{ body }&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;capture&lt;/strong&gt;是外部引用的参数&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;params&lt;/strong&gt;是函数参数&lt;/li&gt;&#10;&lt;li&gt;后面可以跟一些函数修饰符&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;ret&lt;/strong&gt;是返回值类型，如果不指定，会推断一个类型&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;body&lt;/strong&gt;部分是函数内容&#10;具体用法可以参照&lt;a href="http://en.cppreference.com/w/cpp/language/lambda"&gt;C++文档&lt;/a&gt;，这里就不复述了&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这四个声明式都会返回一个匿名的&lt;strong&gt;仿函数&lt;/strong&gt;实例）。&#10;这里有一个比较重要的一点，就是他是一个&lt;strong&gt;仿函数&lt;/strong&gt;实例，而不是直接一个&lt;strong&gt;函数&lt;/strong&gt;。&lt;/p&gt;</description></item><item><title>捣鼓一个协程库</title><link>//owent.net/2014/1000.html</link><pubDate>Wed, 05 Mar 2014 21:52:49 +0000</pubDate><guid>//owent.net/2014/1000.html</guid><description>&lt;p&gt;今年准备安安心心写一个协程库。一方面是觉得协程挺有意思，另一方面也是因为C/C++在这方面没有一个非常权威的解决方案。&#10;按照我自己风格还是喜欢C++，所以协程库定名为 libcopp 。&#10;源码托管在 github: &lt;a href="https://github.com/owent/libcopp"&gt;https://github.com/owent/libcopp&lt;/a&gt;&#10;镜像托管 &lt;a href="http://git.oschina.net/owent/distinctionpp"&gt;http://git.oschina.net/owent/distinctionpp&lt;/a&gt;&lt;/p&gt;&#10;&lt;h1 id="首先介绍-什么是协程"&gt;首先介绍: 什么是协程&lt;/h1&gt;&#10;&lt;p&gt;协程(coroutine)，是一种用户态模拟线程的组件。（具体说明参见：&lt;a href="http://zh.wikipedia.org/wiki/%E5%8D%8F%E7%A8%8B"&gt;http://zh.wikipedia.org/wiki/%E5%8D%8F%E7%A8%8B&lt;/a&gt;）&lt;/p&gt;</description></item><item><title>C++11动态模板参数和type_traits</title><link>//owent.net/2014/971.html</link><pubDate>Mon, 27 Jan 2014 16:27:46 +0000</pubDate><guid>//owent.net/2014/971.html</guid><description>&lt;p&gt;C++11标准里有动态模板参数已经是众所周知的事儿了。但是当时还有个主流编译器还不支持。&#10;但是现在，主要的编译器。VC(Windows),GCC(Windows,Linux),Clang(Mac,IOS)都已经支持了。所以就可以准备用于生产环境了。&#10;type_traits没啥好说的。主要是一些静态检测。主要还是要看动态模板参数和他们两的结合使用上。&#10;动态模版参数标准文档见:&#10;&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf"&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf&lt;/a&gt;&#10;和&#10;&lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf"&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf&lt;/a&gt;&#10;虽然贴出来了。估计是没人看得。所以就直接说重点。&lt;/p&gt;</description></item><item><title>std和boost的function与bind实现剖析</title><link>//owent.net/2013/938.html</link><pubDate>Thu, 28 Nov 2013 22:01:30 +0000</pubDate><guid>//owent.net/2013/938.html</guid><description>&lt;!-- toc --&gt;&#13;&#10;&lt;p&gt;用过std和boost的function对象和bind函数的童鞋们都知道这玩意用起来腰不酸了，腿不疼了，心情也舒畅了。先上一个简单得示例：&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-cpp"&gt;std::string str;&#13;&#10;std::function&amp;lt;bool()&amp;gt; func = std::bind(&amp;amp;std::string::at, &amp;amp;str);&#13;&#10;bool is_empty = func();&lt;/code&gt;&lt;/pre&gt;&#13;&#10;&lt;p&gt;但是这是怎么做到的呢？看完源码以后，你会发现这里面有着一些很巧妙的设计。&lt;/p&gt;</description></item><item><title>不知道是哪一年的腾讯马拉松题目 照片评级 解题报告</title><link>//owent.net/2013/930.html</link><pubDate>Fri, 25 Oct 2013 15:45:05 +0000</pubDate><guid>//owent.net/2013/930.html</guid><description>&lt;p&gt;在某个神奇的下午，收到一个垃圾邮件（至少被邮件系统当成了垃圾邮件）。&lt;/p&gt;&#10;&lt;p&gt;结果就一不小心看到了这个充满回忆的ACM模式竞赛，还有咱腾讯的，就忍不住看了一下。&lt;/p&gt;&#10;&lt;p&gt;果然好久没碰算法，脑子是会生锈的。&lt;/p&gt;&#10;&lt;h2 id="第一题大水懒得写"&gt;第一题大水，懒得写。&lt;/h2&gt;&#10;&lt;h2 id="第二题伤了很久的脑筋想出了一个算法结果ultramanhu基于此想出了个更容易理解更容易实现的方法"&gt;第二题伤了很久的脑筋，想出了一个算法结果ultramanhu基于此想出了个更容易理解更容易实现的方法。&lt;/h2&gt;&#10;&lt;p&gt;以我这种懒人的本性，必须是也懒得写得。&lt;/p&gt;</description></item><item><title>VC和GCC成员函数指针实现的研究(三)</title><link>//owent.net/2013/902.html</link><pubDate>Wed, 11 Sep 2013 14:57:15 +0000</pubDate><guid>//owent.net/2013/902.html</guid><description>&lt;p&gt;接上一篇 &lt;a href="https://www.owent.net/2013/896.html"&gt;VC和GCC内成员函数指针实现的研究(二)&lt;/a&gt;&lt;/p&gt;&#10;&lt;h2 id="虚继承"&gt;虚继承&lt;/h2&gt;&#10;&lt;p&gt;终于到最后的虚继承了。&lt;/p&gt;&#10;&lt;p&gt;测试代码如下:&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-cpp"&gt;#include &amp;lt;ctime&amp;gt;&#13;&#10;#include &amp;lt;vector&amp;gt;&#13;&#10;#include &amp;lt;algorithm&amp;gt;&#13;&#10;#include &amp;lt;cstdio&amp;gt;&#13;&#10;#include &amp;lt;stdint.h&amp;gt;&#13;&#10;#include &amp;lt;cstddef&amp;gt;&#13;&#10;#include &amp;lt;string&amp;gt;&#13;&#10;&#13;&#10;class foo_a&#13;&#10;{&#13;&#10;public:&#13;&#10; virtual ~foo_a(){}&#13;&#10; virtual void info() {&#13;&#10; printf(&amp;#34;%s:%d\n&amp;#34;, __FUNCTION__, __LINE__);&#13;&#10; }&#13;&#10;&#13;&#10; void print(){&#13;&#10; printf(&amp;#34;%s:%d\n&amp;#34;, __FUNCTION__, __LINE__);&#13;&#10; }&#13;&#10;};&#13;&#10;&#13;&#10;class foo_l&#13;&#10;{&#13;&#10;public:&#13;&#10; int l;&#13;&#10; foo_l(): l(1){}&#13;&#10;&#13;&#10; virtual void info() {&#13;&#10; printf(&amp;#34;%s:%d\n&amp;#34;, __FUNCTION__, __LINE__);&#13;&#10; }&#13;&#10;};&#13;&#10;&#13;&#10;class foo_r: virtual public foo_a&#13;&#10;{&#13;&#10;public:&#13;&#10; int r;&#13;&#10; foo_r(): r(2){}&#13;&#10;};&#13;&#10;&#13;&#10;class foo_c: virtual public foo_l, public foo_r&#13;&#10;{&#13;&#10;public:&#13;&#10; virtual void info() {&#13;&#10; printf(&amp;#34;%d,%d. %s:%d\n&amp;#34;, l, r, __FUNCTION__, __LINE__);&#13;&#10; }&#13;&#10;};&#13;&#10;&#13;&#10;&#13;&#10;int main(int argc, char* argv[]) {&#13;&#10; void (foo_a::*vptr1)() = &amp;amp;foo_a::info;&#13;&#10; void (foo_l::*vptr2)() = &amp;amp;foo_l::info;&#13;&#10; void (foo_a::*ptr)() = &amp;amp;foo_a::print;&#13;&#10;&#13;&#10; foo_c c;&#13;&#10; foo_r r;&#13;&#10; foo_a a;&#13;&#10;&#13;&#10; printf(&amp;#34;pword size = %d\n&amp;#34;, (int)(sizeof(size_t)));&#13;&#10; printf(&amp;#34;address of &amp;amp;foo_a::info = 0x%llxH\n&amp;#34;, &amp;amp;foo_a::info);&#13;&#10; printf(&amp;#34;pointer to &amp;amp;foo_a::info = 0x%llxH\n&amp;#34;, vptr1);&#13;&#10; printf(&amp;#34;sizeof vptr = %d\n&amp;#34;, (int)(sizeof(vptr1)));&#13;&#10;&#13;&#10; (a.*vptr1)();&#13;&#10; (r.*vptr1)();&#13;&#10; (c.*vptr1)();&#13;&#10; (c.*vptr2)();&#13;&#10; c.info();&#13;&#10;&#13;&#10; (c.*ptr)();&#13;&#10;&#13;&#10; return 0;&#13;&#10;}&lt;/code&gt;&lt;/pre&gt;&#13;&#10;&lt;h2 id="vc虚继承成员函数指针实现"&gt;VC虚继承成员函数指针实现&lt;/h2&gt;&#10;&lt;p&gt;因为是兼容虚继承和非虚继承的，所以赋值的部分的汇编是一样的。这里就不贴了。关键在于执行期它是怎么找到虚基类的。请往下看：&lt;/p&gt;</description></item><item><title>VC和GCC成员函数指针实现的研究(二)</title><link>//owent.net/2013/896.html</link><pubDate>Wed, 11 Sep 2013 14:44:06 +0000</pubDate><guid>//owent.net/2013/896.html</guid><description>&lt;p&gt;接上一篇 &lt;a href="https://www.owent.net/2013/890.html"&gt;VC和GCC内成员函数指针实现的研究(一)&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;接下来是多重继承，用到的测试代码如下所示:&lt;/p&gt;&#10;&lt;pre&gt;&lt;code class="language-cpp"&gt;#include &amp;lt;ctime&amp;gt;&#13;&#10;#include &amp;lt;vector&amp;gt;&#13;&#10;#include &amp;lt;algorithm&amp;gt;&#13;&#10;#include &amp;lt;cstdio&amp;gt;&#13;&#10;#include &amp;lt;stdint.h&amp;gt;&#13;&#10;#include &amp;lt;cstddef&amp;gt;&#13;&#10;#include &amp;lt;string&amp;gt;&#13;&#10;&#13;&#10;class foo_a&#13;&#10;{&#13;&#10;public:&#13;&#10; virtual ~foo_a(){}&#13;&#10; virtual void info() {&#13;&#10; printf(&amp;#34;%s:%d\n&amp;#34;, __FUNCTION__, __LINE__);&#13;&#10; }&#13;&#10;};&#13;&#10;&#13;&#10;class foo_b&#13;&#10;{&#13;&#10;public:&#13;&#10; virtual ~foo_b(){}&#13;&#10;&#13;&#10; // 这个函数用于试foo_b的结构与foo_a不同&#13;&#10; // 以防止VC对foo_a和foo_b的`vcall&amp;#39;{8}&amp;#39;的代码合并&#13;&#10; virtual void inspect() { &#13;&#10; printf(&amp;#34;%s:%d\n&amp;#34;, __FUNCTION__, __LINE__);&#13;&#10; } &#13;&#10;&#13;&#10; virtual void info() {&#13;&#10; printf(&amp;#34;%s:%d\n&amp;#34;, __FUNCTION__, __LINE__);&#13;&#10; }&#13;&#10;&#13;&#10; void print() {&#13;&#10; printf(&amp;#34;%s:%d\n&amp;#34;, __FUNCTION__, __LINE__);&#13;&#10; }&#13;&#10;};&#13;&#10;&#13;&#10;&#13;&#10;class foo_c: public foo_a, public foo_b&#13;&#10;{&#13;&#10;public:&#13;&#10; virtual void info() {&#13;&#10; printf(&amp;#34;%s:%d\n&amp;#34;, __FUNCTION__, __LINE__);&#13;&#10; }&#13;&#10;};&#13;&#10;&#13;&#10;&#13;&#10;int main(int argc, char* argv[]) {&#13;&#10; void (foo_a::*vptr1)() = &amp;amp;foo_a::info;&#13;&#10; void (foo_b::*vptr2)() = &amp;amp;foo_b::info;&#13;&#10; void (foo_b::*ptr)() = &amp;amp;foo_b::print;&#13;&#10;&#13;&#10; foo_c c;&#13;&#10; foo_b b;&#13;&#10; foo_a a;&#13;&#10;&#13;&#10; &#13;&#10; printf(&amp;#34;word size = %d\n&amp;#34;, (int)(sizeof(size_t)));&#13;&#10; printf(&amp;#34;address of &amp;amp;foo_a::info = 0x%llxH\n&amp;#34;, &amp;amp;foo_a::info);&#13;&#10; printf(&amp;#34;pointer to &amp;amp;foo_a::info = 0x%llxH\n&amp;#34;, vptr1);&#13;&#10; printf(&amp;#34;address of &amp;amp;foo_b::info = 0x%llxH\n&amp;#34;, &amp;amp;foo_b::info);&#13;&#10; printf(&amp;#34;pointer to &amp;amp;foo_b::info = 0x%llxH\n&amp;#34;, vptr2);&#13;&#10; printf(&amp;#34;sizeof vptr = %d\n&amp;#34;, (int)(sizeof(vptr1)));&#13;&#10;&#13;&#10; (a.*vptr1)();&#13;&#10; (b.*vptr2)();&#13;&#10; (c.*vptr1)();&#13;&#10; (c.*vptr2)();&#13;&#10;&#13;&#10; (c.*ptr)();&#13;&#10;&#13;&#10; return 0;&#13;&#10;}&lt;/code&gt;&lt;/pre&gt;&#13;&#10;&lt;h2 id="vc多重继承成员函数指针实现"&gt;VC多重继承成员函数指针实现&lt;/h2&gt;&#10;&lt;p&gt;&lt;img src="//owent.net/2013/p896_img8.png" loading="lazy" /&gt;&lt;/p&gt;</description></item><item><title>VC和GCC内成员函数指针实现的研究(一)</title><link>//owent.net/2013/890.html</link><pubDate>Fri, 06 Sep 2013 12:55:58 +0000</pubDate><guid>//owent.net/2013/890.html</guid><description>&lt;p&gt;最近在《C++对象模型》一书里说到的virtual的成员函数指针，低于128的被cfront编译器认为是虚表偏移量（支持子类对父类函数的覆盖）。VC只是提了下单继承、多继承和虚继承的实现方案不同，GCC没有提及，所以就专门稍微深入分析研究下他们的实现机制。&lt;/p&gt;</description></item></channel></rss>