134-C++ learning eighth bullet

Overload[]

Version one

char&operator[](const int index)
{
    
    
	assert(index>=0&&index<strlen(str));
	return str[index];
}

const char&operator[](const int index)const
{
    
    
	assert(index>=0&&index<strlen(str));
	return str[index];
}

const char*c_str()const
{
    
    
	return str;
}

int main()
{
    
    
  String s1("yhpinghello");
  char x=s1[1];
  return 0;
  
}

Flexible array

Insert picture description here
Insert picture description here
Insert picture description here
For flexible arrays, it is not calculated in the size of the structure. The size of the
Insert picture description here
structure is 8 and the structure occupies 8 bytes, and the rest is for data

Overload [] version two

class String
{
    
    
	struct StrNode
	{
    
    
		int len;	// 字符串的长度
		int size;	// 记录柔性数组的大小;sizeof(StrNode)+len
		//int ref;	// 引用计数
		atomic<int> ref;
		char data[];// 柔性数组	存字符串
	};
private:
	StrNode* str;
public:
	String(const char *s = nullptr)	:str(nullptr)//构造函数 
	{
    
    
		if (s != nullptr) // s = "tulun"
		{
    
    
			int len = strlen(s);
			str = (StrNode*)malloc(sizeof(StrNode) + 2 * (len + 1));
			if (str == nullptr) exit(EXIT_FAILURE);//申请空间失败 
			str->len = len;
			str->size = 2 * (len + 1);//空间的大小,不算结构体,只记录柔性数组大小 
			str->ref = 1; //有对象指向字符串 
			strcpy_s(str->data, len + 1, s);
		}
	}
	
	~String()//析构函数 
	{
    
    
		if (str != nullptr && --str->ref == 0)
		{
    
    
			free(str);
		}
		str = nullptr;
	}
}	

Copy constructor
Insert picture description here

String(const String &s):str(s.str)//拷贝构造函数 
{
    
    
	if (str != nullptr)
	{
    
    
		str->ref += 1;
	}
}
int main()
{
    
    
	String s1("yhpinghello");
	String s2(s1);
	String s3(s1);
	String s4(s1);
	return 0;
}

The construction process is shown in the figure below. When
Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here
destructuring, ref–;
if s1 has been destructed, it cannot be used to construct s2 s3 s4

Overloaded assignment function

int main()
{
    
    
	String s1("yhpinghello");
	String s2(s1);
	String s3("tulun");
	String s4(s3);
	s2 = s3;
	return 0;
}

Insert picture description here
When s2=s3 is executed,
the str of s2 does not point to yhpinghello, the ref in the space of yhpinghello becomes 1, the str of s2 points to tulun, and the ref of this space of tulun becomes 3.

If s1=s3 is executed again
, the str of s1 points to tulun, The ref in the yhpinghello space becomes 0, and the ref in the tulun space becomes 4

String& operator=(const String& s)
{
    
    
	if (this != &s)
	{
    
    
		if (this->str != nullptr && --this->str->ref  == 0)
		{
    
    
			free(str);
		}
		str = s.str;
		if (str != nullptr)
		{
    
    
			str->ref += 1;
		}
	}
	return *this;
}

Insert picture description here
Look at the following code


String fun()
{
    
    
	String tmp("yhping");
	return tmp;	 // return String("yhping");
		
}
int main()
{
    
    
	String s1("tulun");
	String s2(s1);
	String s3 = fun();
	
	String s4;
	s4 = fun();

	return 0;
}

	
String(String&& s)
{
    
    
	str = s.str;
	s.str = nullptr;
}
String& operator=(String&& s)
{
    
    
	if (this != &s)
	{
    
    
		if (this->str != nullptr && --this->str->ref == 0)
		{
    
    
			free(str);
		}
		str = s.str;
		s.str = nullptr;
	}
	return *this;
}

Insert picture description here
Constructed with return String("yhping"); this way, the system is optimized, and the return construction object is directly s3 itself.
If you are constructing tmp, first construct the tmp object, and then assign tmp to construct s3, and move the construction in the
Insert picture description here
Insert picture description here
above two cases , How to overload +=?

Copy-on-write

Overload +=
Insert picture description here If the tulun string is too long, you need to reapply. The
best way is as follows

String& operator+=(const String& s)
{
    
      
	// s1 += s2;
	//NULL NULL;
	//NULL not
	//not NULL;
	//not not;

	if (this->str == nullptr || s.str == nullptr)
	{
    
    
		this->str = s.str;
		if (this->str != nullptr)
		{
    
    
			this->str->ref += 1;
		}
	}
	else if (this->str != nullptr && this->str->ref == 1)
	{
    
    
		int dist = this->str->size - this->str->len - 1;
		if (dist >= s.str->len)
		{
    
    
			strcat_s(this->str->data,this->str->size, s.str->data);
		}
		else//剩余空间拷贝不进去
		{
    
    
		    str=(StrNode*)realloc(sizeof(StrNode)+sp->len + s.str->len + 1);
		    strcat_s(this->str->data,this->str->size, s.str->data);
		}
	}
	else
	{
    
    
		StrNode* sp = this->str;
		this->str->ref -= 1;
		this->str = nullptr; 
		int total = sp->len + s.str->len + 1;//总的字节数
		str = (StrNode*)malloc(sizeof(StrNode) + 2 * total);//开辟空间
		str->len = total - 1;//字符串长度
		str->size = 2 * total;//空间大小个数
		str->ref = 1;
		strcpy_s(str->data,str->size, sp->data);
		strcat_s(str->data, str->size, s.str->data);
	}
	return *this;
}

Insert picture description here
Insert picture description here

Overload[]

int main()
{
    
    
	String s1("yhpinghello");
	String s2(s1);
	String s3("tulun");
	char x = s3[1];
	x = s1[2];
	s1[2] = 'W';

	return 0;
}
const char& operator[](const int index) const//常方法,不改变
{
    
    
	assert(str != nullptr && index >= 0 && index < str->len);
	return str->data[index];
}

char& operator[](const int index)//普通方法
{
    
    
	assert(str != nullptr && index >= 0 && index < str->len);
	if (str->ref > 1)
	{
    
    
		str->ref -= 1;//断绝关系
		StrNode* sp = str;
		str = (StrNode*)malloc(sizeof(StrNode) + sp->size);
		str->len = sp->len;
		str->size = sp->size;
		str->ref = 1;
		strcpy_s(str->data, str->size, sp->data);
	}
	return str->data[index];
}

Typical copy
Insert picture description here
funA when writing, build sa, call the copy constructor, not empty, ref is 1, first take out 1, add 1 and then write in, but this 1 has been read out, add 1 to write When it entered, it was interrupted. Thread B came in, constructed the b object, entered, it is not empty, ref is taken out as 1, and after 1 is added, it is 2. When preparing for the follow-up, the 1 (dirty number) read before is added in , The last is 2, the competition relationship, resulting in three objects, ref=2, when the program exits, ref–,ref=0, causing the final program to fail How to change the
resource contention of threads
?
ref do not define integer
Insert picture description here
++a for execution, there are many lines of machine code
that may be interrupted by other statements.
How to solve
atomic operations (indivisible)

atomic<int> ref;

Can’t be done, and other threads can’t proceed

Guess you like

Origin blog.csdn.net/LINZEYU666/article/details/112683141