一.CPP
1.string三种历史实现
- 浅拷贝:只要赋值即new空间进行深拷贝
- 增加引用计数,不修改则计数加一,修改则深拷贝
- 当字符串的长度小于等于15个字节时,buffer直接存放整个字符串;当字符串大于 15个字节时,buffer存放的就是一个指针,指向堆空间的区域。这样做的好处是, 当字符串较小时,直接拷贝字符串,放在string内部(通常为栈),不用获取堆空间,开销小。
class string {
union Buffer{ char * _pointer; char _local[16]; };
Buffer _buffer; size_t _size; size_t _capacity;
};
2.最佳策略
以上三种方式,都不能解决所有可能遇到的字符串的情况,各有所长,又各有缺 陷。综合考虑所有情况之后,facebook开源的folly库中,实现了一个fbstring, 它根 据字符串的不同长度使用不同的拷贝策略, 最终每个fbstring对象占据的空间大小 都是24字节。
-
很短的(0~22)字符串用SSO,23字节表示字符串(包括’\0’),1字节表示长度
-
中等长度的(23~255)字符串用eager copy,8字节字符串指针,8字节size, 8字节capacity.
-
很长的(大于255)字符串用COW, 8字节指针(字符串和引用计数),8字节 size,8字节capacity.
该技术目前在多核处理器不能很好的实现,目前大部分系统采用sso方法
CPU的原子操作虽然比mutex锁好多了, 但是仍然会带来性能损失, 原因如下:
- 阻止了CPU的乱性执行.
- 两个CPU对同一个地址进行原子操作, 会导致cache失效, 从而重新从内存中读数据.
- 系统通常会lock住比目标地址更大的一片区域,影响逻辑上不相关的地址访问
作业:分离[]后的读写操作
class String{
public:
//内部友元类,区别派生类
class CharProxy{
public:
CharProxy(String &str, int index);
CharProxy& operator=(const CharProxy&rhs);//左值运用
CharProxy& operator=(char c);
operator char()const;//右值运用
private:
String &theString;
int charIndex;
};
const CharProxy operator[](int index)const;
CharProxy operator[](int index);
friend class CharProxy;
private:
RCPtr<StringValue>value;
};
//重载String类下标符,两版
const String::CharProxy String ::operator[](int index)const {
return CharProxy(const_cast<String&>(*this), index);
}
String::CharProxy String::operator[](int index){
return CharProxy(*this, index);
}
//构造内部类类型
String::CharProxy::CharProxy(String &str, int index) :theString(str), charIndex(index){}
//重载内部类char转换操作
String::CharProxy::operator char()const{
return theString.value->data[charIndex];
}
//重载内部类赋值
String::CharProxy&String::CharProxy::operator=(const CharProxy &ths){
if (theString.value->isShared()){
theString.value = new StringValue(theString.value->data);
}
theString.value->data[charIndex] = rhs.theString.value->data[ths.charIndex];
return *this;
}
String::CharProxy&String::CharProxy::operator=(char c){
if (theString.value->isShared()){
theString.value = new StringValue(theString.value->data);
}
theString.value->data[charIndex] = c;
return *this;
}
关于宏
https://blog.csdn.net/yuanxuegui2008/article/details/6385298
参数捕捉的方式导致宏不能解决这个问题
预习下周
1.多态
静态多态:函数运算符重载
动态多态:虚函数(默认)
基类中必须声明,派生类可不加virtual
派生类中重定义必须与基类中返回类型/参数个数/参数类型一致
2.继承