std::string() = "abc"
天哪?临时变量不是右值吗?怎么还能给他赋值?怪哉怪哉
在查询了多方资料后,最终被一句话点醒,“这玩意不就是一个成员函数么?”
啊这,确实,玩意不就是调用了个成员函数么。。。
果然,int() = 5;
就不行,除基础类型外,赋值就相当于.operator=(),右值调用个成员函数还不是小意思,如此一来,也可以对函数返回值赋值,只要他的返回值支持 operator=的重载,如
1 | string foo(){ |
虽然给临时变量或者函数返回值赋值没有多大意义就是了^ ^
另外还有一些奇怪的例子也是可以用操作符重载的角度来解释:
1 |
|
上面的代码也是可以编译通过的,而且会输出 11,实际上[]也就是一个双目操作符,它对于两个操作数的顺序没有严格要求,a[1]相当于*(a + 1)
,1[a]相当于*(1 + a)
,由于 a 在参数传递时会退化成数组首地址,所以他们是等价的
意外的收获:
在探究 std::string() = “abc”的同时,还了解到了 sso 的概念:
1 |
|
Linux 5.15 用 clang++编译运行会输出
1 | malloc 17 bytes |
如果使用 gcc 则不会输出任何东西,这与编译器的底层实现有关
你可能会问,string a、b 不是在栈上的东西吗?为什么会使用到 new 并输出这样的内容呢?
这是因为 cpp 标准库的 string 对小字符串做了优化,也就是 SSO(Small String Optimization),小于等于 16 个字节的字符串会直接存储在栈上,大于 16 个字节的字符串会存储在堆上
“0123456789ABCDE\0”刚好 16 个字节,所以在栈上,不会用到 new,而”0123456789ABCDEF\0”17 个字节,所以在堆上分配了 17 个字节
这里的 new 是 operator new 的重载,并不是我们 new 一个对象的那个 new,我们使用的那个 new 是被封装过的,在此了解
std::string() = "abc"