-
【C++11】字符串与常用数据结构
学习一门编程语言,考察编程语言支持的基本数据结构是很重要的。如果你以前学的C/C++倾向于自己造轮子,或者你有其他语言背景的话,建议重新了解一下C++11 标准库中的数据结构。 字符串 std::string 你可以用 const char* 也就是字符串字面量来构造 std::string ,也可以从 std::string 中获取 C风格字符串的指针(const char*)。 std::string foo = “foo”; foo.c_str(); // const char* std::string 是可变的,所以你可以修改 std::string 而不用太担心性能 std::string result; result += “foo”; result += ‘@’; result += “example.com”; 关于不可变字符串,有很多讨论,这里列举一下想要用不可变的“字符串”话,在不用其他库的情况下可以怎么做 const char* 如果自己分配的字符串数组的话,需要记得delete。字符串字面量的话不用担心。 const std::string& 给 std::string 加const,严格来说这只是防止修改 自己造轮子 std::string 支持 copy 和 move std::string 的 substr…
-
【C++11】字符串拼接之回归原点
在其他语言里,字符串拼接可能是一个常见而且基本不会去注意的部分,但是在C++中字符串拼接有非常多的解决方法。造成这种现象的原因是,C++程序员想要高效地拼接字符串。 比如说下面的代码 std::string concat_string(const std::string& name, const std::string& domain) { return name + ‘@’ + domain; } 对于有非C/C++语言的人来说可能最平常不过的代码,C++程序员可能直觉上不会采用这种写法。那么C++里面该用什么写法呢?或者说最佳实践是什么? 这里不会列举各种字符串拼接的方式,如果你有兴趣可以在StackOverflow上搜搜看。个人想要说的是:在分析了C++11里字符串的操作之后个人给出的结论:C++11里最佳的字符串拼接其实就是上述写法。以下是具体分析。
-
【C++11】move构造函数和std::move
如果说新的语言特性使得过去的最佳实践不再成立的话,我想move构造函数和std::move所代表的move语义应该算其中一个。 在解释move引起的变化之前,这里先定义一个支持自定义move操作的类 class Foo { public: explicit Foo(int value) : value_{value} { std::cout << “Foo(int)\n”; } // copy Foo(const Foo &foo) : value_{foo.value_} { std::cout << “Foo(copy)\n”; } // copy assignment Foo &operator=(const Foo &foo) = delete; // move Foo(Foo &&foo) { std::cout << “Foo(move)\n”; value_ = foo.value_; foo.value_ = 0; } // move assignment…
-
【C++11】从std::string str = “foo”说开去
最近因为某些原因决定重新开始学习C++。考虑到自己在大学里面学到的C++有点旧(估计是C++98),所以打算从C++11开始。 C++11如其名,是2011年出来的标准,所以2011年之后才有编译器实现。现在2019年大部分PC以及服务器应该都支持C++11了。 个人习惯于看书来学习某样东西,所以找了C++相关书的资料。一开始在o’reilly上找,发现很多书都比较旧。虽然有Effective C++以及More Effective C++系列,但对于初学者来说还不是时候。最后在Stackoverflow上找到了一个比较全的推荐书列表 https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list
-
Java并发研究 自己写ReentrantLock和ReentrantReadWriteLock(4)
接上篇。在写完ReentrantLock之后,其实可以基于ReentrantLock写一个ReadWriteLock,《the art of multiprocessor programming》第八章有介绍。但是,本着不完全AQS(AbstractQueuedSynchronizer)介绍的系列主题,这里从零开始重新写一个ReentrantReadWriteLock。 按照ReadWriteLock的定义,任何时候都满足 没有线程持有锁 有1~n个线程持有共享锁(Read) 有1个线程持有独占锁(Write) 中的一个。 其次公平的ReadWriteLock要求新来的Read或者Write线程必须在队列中等待,非公平的ReadWriteLock允许新来的Read或者Write比队列中等待的线程先获取锁。关于非公平锁这里多说一句,理论上的非公平锁类似一群人哄抢的现象,但是实现多半是只允许新来和线程队列最前面的线程抢占锁。ReadWriteLock也是一样。如果你想要完全非公平的锁的话,可能AQS和这里的实现不满足你的需求。 为了实现ReadWriteLock的定义,你需要分别记录读写状态。考虑到独占(Write)状态只可能有一个线程,可能场景如下:
-
raspberry pi 3 b+ cross compile on macos mojave
本文记录了如何在mojave上构建raspberry pi 3 b+的交叉编译环境。交叉编译的原因最主要的还是速度,当然还有目标平台没有直接的编译工具链等。在构建交叉编译环境之前,最好确认目标平台的相关信息,能直接确认目标平台的工具链是最好的,因为从CPU判断可能并不准确。 比如raspebrry pi 3 b+,自带gcc,相关信息如下 Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/6/lto-wrapper Target: arm-linux-gnueabihf Configured with: ../src/configure -v –with-pkgversion=’Raspbian 6.3.0-18+rpi1+deb9u1′ –with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs –enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ –prefix=/usr –program-suffix=-6 –program-prefix=arm-linux-gnueabihf- –enable-shared –enable-linker-build-id –libexecdir=/usr/lib –without-included-gettext –enable-threads=posix –libdir=/usr/lib –enable-nls –with-sysroot=/ –enable-clocale=gnu –enable-libstdcxx-debug –enable-libstdcxx-time=yes –with-default-libstdcxx-abi=new –enable-gnu-unique-object –disable-libitm –disable-libquadmath –enable-plugin –with-system-zlib –disable-browser-plugin –enable-java-awt=gtk –enable-gtk-cairo –with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-armhf/jre –enable-java-home –with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-armhf –with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-armhf –with-arch-directory=arm –with-ecj-jar=/usr/share/java/eclipse-ecj.jar –with-target-system-zlib –enable-objc-gc=auto –enable-multiarch…
-
Compile and install valgrind on macOS Mojave (10.14.2)
本文是给想在Mojave上编译安装valgrind的人一个参考。 个人因为《Hands on concurrency with Rust》这本书的原因,需要安装valgrind。但是现在(2019/2/9)稳定版本的valgrind尚未支持Mojave,即不能通过Homebrew安装。valgrind的bug tracker里有这个问题的追踪, 但是看状态估计离正式发布还需要时间(开源项目常有的事情,缺少资源,哎)。对话中给了一个github上的commit,看起来可以使用。 下载对应的repository,checkout到修改版的branch上 git clone https://github.com/Echelon9/valgrind.git cd valgrind git checkout feature/v3.14/macos-mojave-support-v2 按照valgrind自身网站上的说明,接下来是常规的compile install。 ./autogen.sh ./configure –prefix=foo make make install 如果你按照顺序执行的话,在make可能会碰到如下两个问题,所以在执行之前,建议先看一下可能碰到的问题 1. No rule to make target `/usr/include/mach/mach_vm.defs’ 简单来说,就是没有找到定义文件。按照stackoverflow上一个问题的说法,你可以通过 xcode-select –install 解决,但是答案针对的不是Mojave,所以Mojave除了通过上述命令安装XCode之外,还需要解答中另外一个解决方案,即修改coregrind/Makefile(此文件在./configure之后生成)中mach_vm.defs的路径,具体如下 am__append_19 = \ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/mach/mach_vm.defs \ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/mach/task.defs \ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/mach/thread_act.defs \ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/mach/vm_map.defs 也就是在原本 /usr/include/mach/mach_vm.defs 等文件前加上 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk 前缀,你可以 ls 一下看一下文件是否存在。 2.…
-
如何理解 C++11 原子变量(Atomic)的 Memory Order
最近几天在学习Rust,把Rust官网附带的The Rust Programming Language看完,开始尝试用Rust实现自己学习过的并发数据结构。首先碰到的问题是,如何理解Rust所基于的LLVM的atomics模型。因为LLVM的原子变量模型基本可以对应于C++11开始的原子变量,除了没有consume memory order。所以任务就变成了如何理解C++11的原子变量。 C++原子变量本身并不难理解,但是理解memory order很难。网上找了很多资料,都没有很清晰得解释memory order到底是什么。今天重新看了《C++ Concurrency in Action》关于memory order的部分,对照着 std::memory_order 的介绍,突然明白了这是怎么一回事。 答案是memory order就只是一个order。