考虑下面实现的类(基本上是为了MCVE) (假设是little endian、64位指针等):
class String { char* data_; bool sso() const { return reinterpret_cast<uintptr_t>(data_) & 1; } public: String(const char * arg = "") { auto len = strlen(arg); if (len > 6) { data_ = new char[len + 1]; memcpy(data_, arg, len + 1); } else { data_ = reinterpret_cast<char*>((uintptr_t)1); memcpy(reinterpret_cast<char*>(&data_) + 1, arg, len + 1); } } ~String() { if (sso() == false) delete data_; } // ~String() { if (reinterpret_cast<uintptr_t>(data_) & 1 == 0) delete data_; } };
static void CreateShort(benchmark::State& state) { for (auto _ : state) { String s("hello"); benchmark::DoNotOptimize(s); } }
快5.7倍
与叮当声,没有区别,这两个变种是快速的。
问题是转换成 bool
bool
~String() { if ((bool)(reinterpret_cast<uintptr_t>(data_) & 1) == false) delete data_; }
对于此代码:
if (reinterpret_cast<uintptr_t>(data_) & 1 == 0) delete data_;
它可以完全优化: 1 == 0 0 ,和 x & 0 对所有人来说都是假的 x . 第一种情况比较慢,因为它实际上在做一些事情。
1 == 0
0
x & 0
x
我想你的意思是:
if ( (reinterpret_cast<uintptr_t>(data_) & 1) == 0) delete data_;
我用的一个助记符来表示 & | 我们要回顾的是,在C的前体中,没有单独的运算符 & 和 && & 运算符同时完成了这两个角色(如果需要逻辑比较,可以手动将其转换为布尔值范围)。所以呢 x == y & z == w 是检查这两个等式是否成立的正常代码。
&
|
&&
x == y & z == w
什么时候? && 为了避免破坏现有的代码, && 优先级低于 & ;但是 & == .
==