【c++】string模拟实现

string类的接口

namespace zjw
{
	class string
	{public:
		typedef char* iterator;
		typedef   const char* const_iterator;
	private:
		char* _str;
		int _size;
		int _capacity;



	};

这里的迭代器直接使用原生指针来封装。
_str为指向string数组的首地址的指针。
_size为string数组的大小。
_capacity为string数组的容量

基本函数

实现 函数返回string的首地址;
实现 函数返回string的尾地址;
实现 函数返回string的大小;
实现 函数返回string的容量;

	iterator begin()
		{
			return _str;
		
		
		
		}
	iterator end()
		{
			return _str+_size;



		}
	size_t size()
		{
			return _size;
		
		
		
		
		}
	size_t capacity()
		{
			return _capacity;

		
		}

如果一个string类不能被修改的话,就无法调用非const的成员函数
在这里插入图片描述

	const_iterator begin() const
		{
			return _str;



		}
		const_iterator end() const
		{
			return _str + _size;



		}

默认构造以及析构函数

	string(const char* str = "")
			:_size(strlen(str))
		{
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
		~string()
		{ 
			delete[]_str;
			_str = nullptr;
			_size = _capacity = 0;

		
		
		
		
		}

这里有一个问题,就是默认构造传的缺省参数可以是nullptr 吗??
答案是不行的,因为strlen要将str解引用找’\0’,如果传nullptr的话,对空指针解引用就会出错。
这里也不可以传单字符‘\0’,因为这里的str是const char* 类型,而’\0’是char 类型


运算符重载下标访问函数

	char& operator[](size_t pos)
		{
			assert(pos<_size);
			return _str[pos];

		
		
		}
		const char& operator[](size_t pos) const
		{
			assert(pos < _size);
			return _str[pos];



		}

下标为_size的地方存的是’\0’,所以不用访问,pos<_size,为了让const迭代器不修改对于下标的值,修改上面得到下面,对上面进行函数重载

reserve函数

	void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[]_str;
				_str = tmp;
				_capacity = n;

			}
		
		
		
		
		
		}

在这里插入图片描述
注意:这里多开一个是为了存’\0’;

push_back()函数

	void push_back(char ch)
		{
			if (_capacity == _size)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);

			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';


		
		
		
		
		}

原来下标是_size的地方是‘\0’,然后之间在_size的地方放入ch,_size++,染后在补一个’\0’;要插入数据的一半都要扩容

append函数

	void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);

			}
			strcpy(_str + _size, str);
			_size += len;
			//_str[_size] = '\0';

		}

尾插一个字符串,如果string的大小+要插入的字符串大小>_capacity,就扩容到_size + len,刚好,strcpy会从str开始直到遇到‘\0’一个字节一个字节拷贝到_str + _size(原字符串’\0’的地方),这里会把str字符串后面的‘\0’也拷贝过来。

运算符重载+=字符以及+=字符串

	string& operator+=(char ch)
		{
			push_back(ch);
			return *this;

		
		
		}
		string& operator+=(const char* str)
		{
			append(str);
			return *this;

		



		}

在这里传引用返回是因为_str指向的空间是在堆上开的,出函数不会被销毁,所以可以传引用返回

insert函数(插入字符)

void insert(size_t pos, char ch)
		{
			assert(pos<=_size);
			if (_capacity == _size)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);

			}
			size_t end = _size;
			while (end >=pos)
			{

				_str[end+1] = _str[end];
				end--;


			}
			_str[pos] = ch;
			_size++;

		
		
		
		
		
		}

上面这个写法可以吗??
是不可以的
在这里插入图片描述
怎么修改呢??

	void insert(size_t pos, char ch)
		{
			assert(pos<=_size);
			if (_capacity == _size)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);

			}
			size_t end = _size+1;
			while (end >pos)
			{

				_str[end] = _str[end-1];
				end--;


			}
			_str[pos] = ch;
			_size++;

		
		
		
		
		
		}

这样就可以了,我们从’\0’的下一个位置开始end,此时end结束的条件是=0,所以不会陷入循环,这里和顺序表的insert很像,可以参考顺序表那里。


earse函数

	void earse(size_t pos, size_t len = npos)
		{
			assert(pos < _size);
			if (len == npos || pos > _size-len)
			{
				_str[pos] = '\0';
				_size = pos;
				

			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;

			}
			
		
		
		
		
		
		
		}

删除从pos位置开始的len个字符长度的字符,如果len大于剩下的字符,就全删了,这里给的缺省值为npos=-1,可以认为是很大的数,绝对超过了pos后面的字符数,我们要在string里面声明一个npos,在类外面定义初始化。
在这里插入图片描述

如果len==npos或者len+pos>_size,就始要将pos开始后面的字符串全删除,我们直接在pos位置放’\0’即可,
_size=pos;
如果没有超过字符串
在这里插入图片描述


insert(插入字符串)

void insert(size_t pos, const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);

			}
			size_t end = _size + len;
			while (end > pos + len - 1)
			{
				_str[end] = _str[end - len];
				end--;

			}
			strncpy(_str + pos, str, len);
			_size += len;


		}

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9d88ba8502954c0dbd884890654c612a.png

void test6()
	{
		string str;
		str.push_back('a');
		str.push_back('a');
		str.push_back('b');
		str.insert(2, "hello");
		cout << str.c_str();




	}

swap

	void swap(string& str)
		{
			std::swap(_str, str._str);
			std::swap(_size, str._size);
			std::swap(_capacity, str._capacity);

}
	void test12()
	{   string str1;
		string str2;
		str1 += "hello";
		str2+="nihao";
		cout << "str1:"<<str1 << endl;
		cout << "str2:"<<str2 << endl;
		str1.swap(str2);
		cout << "str1:" << str1 << endl;
		cout << "str2:" << str2 << endl;

	}

在这里插入图片描述


这里我们自己实现的swap是类成员函数,但是#include< algorithm >这个头文件库里面也有一个swap,swap全局也有一个非成员函数swap

在这里插入图片描述

我们可以发现算法库中的swap需要完成三次的拷贝,以及一次析构(临时变量c的析构),而string里面定义一个全局的swap,就是为了防止调用算法库里面的swap,因为会先在全局找,然后会在展开的库里找,而全局的swap实现只需要调用类里面的swap即可

	void swap(string& x, string& y)
	{
		x.swap(y);
		cout << "没使用库里的" << endl;
	
	}
	void test13()
	{
		string str1;
		string str2;
		str1 += "hello";
		str2 += "nihao";
		cout << "str1:" << str1 << endl;
		cout << "str2:" << str2 << endl;
		swap(str1, str2);//检测是调用库里的,还是全局的
		cout << "str1:" << str1 << endl;
		cout << "str2:" << str2 << endl;
	
	
	}

在这里插入图片描述

赋值以及拷贝构造

	string(const string& s)
		{
			string tmp(s._str);
			swap(tmp);
		
		
		
		
		}
		string& operator=(string tmp)
		{
			swap(tmp);
			return *this;
		}

根据调试发现
在这里插入图片描述

老版本赋值

		string& operator=(const string& s)
		{
			char* tmp = new char[s._capacity + 1];
			strcpy(tmp, s._str);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
			return *this;

			




			

		}

find函数(查找字符)

	size_t find(char ch, size_t pos = 0)
		{

			for (int i = pos; i < _size; i++)
			{
				if (_str[i] == ch)
					return i;



			}
			return npos;





		}

从pos位置开始查找,如果pos使用缺省,则从第一个位置开始查找,从pos位置开始遍历,如果找到返回下标,如果找不到返回npos

	void test7()
	{
		string str;
		str.push_back('a');
		str.push_back('a');
		str.push_back('b');
		str.insert(2, "hello");
		cout << endl;
		int ret = str.find('b', 0);
		cout << ret;


	}

在这里插入图片描述


find函数(查找子串)

		size_t find(const char* sub, size_t pos = 0) const
		{
			assert(pos < _size);//下标为_size的是‘\0’
			const char* ptr = strstr(_str + pos, sub);
			if (ptr != nullptr)//找到了,但是strstr返回的是找到子串的起始地址-字符串起始地址就是子串相对起始位置的长度
			{
				return ptr - _str;

			}
			else
			{
				return npos;
			}





		}
	void test8()
	{
		string str;
		str += "beijing huanyingni zhangjiawang";
		int ret = str.find("zhangjiawang");
		cout << ret;




	}

在这里插入图片描述


substr函数

string substr(size_t pos = 0, size_t len = npos) const
		{
			string substr;

			if (pos > _size - len)
			{
				for (int i = pos; i <= _size; i++)
				{
					substr += _str[i];
				}


			}
			else
			{

				for (int i = pos; i < pos + len; i++)
				{
					substr += _str[i];
				}
				substr += '\0';

			}
			return substr;





		}

从pos位置开始取,取len个长度,分两种情况,如果从pos开始还没取到len长,就结束,就取到结尾,遍历pos到_size,string substr 保存遍历的值.
第二种,遍历pos到pos+len,string substr 保存遍历的值.最后记得加‘\0’;
在这里插入图片描述

运算符重载比较函数

	bool operator==(const string& s1, const string& s2)
	{
		return strcmp(s1.c_str(), s2.c_str())==0;



	}
	bool operator>(const string& s1, const string& s2)
	{
		return strcmp(s1.c_str(), s2.c_str());



	}
	bool operator<(const string& s1, const string& s2)
	{
		return  !(s1 > s2 && s1 == s2);



	}
	bool operator<=(const string& s1, const string& s2)
	{
		return  !(s1 > s2);



	}
	bool operator>=(const string& s1, const string& s2)
	{
		return  !(s1 < s2);



	}
	bool operator!=(const string& s1, const string& s2)
	{
		return  !(s1 == s2);



	}

注意这里为什么要搞成全局的呢??

	void test10()
	{
		string str1;
		string str2;
		str1 += "abc";
		str2 += "aba";

		cout << (str1 == str2) << endl;
		cout << ("aba" == str2) << endl;//2
		cout << (str2== "aba") << endl;




	}

因为第二种的话不满足类成员做左操作数,全局的话就可以,而第三个是会搞一个类型转换.

	void test10()
	{
		string str1;
		string str2;
		str1 += "abc";
		str2 += "aba";

		cout << (str1 == str2) << endl;
		cout << ("aba" == str2) << endl;
		cout << (str2== "aba") << endl;
		 cout << (str1>str2) << endl;
		 cout << (str1 >=str2) << endl;
		 cout << (str1<str2) << endl;
		 cout << (str1 <=str2) << endl;
		 cout << (str1!=str2) << endl;




	}

在这里插入图片描述


运算符重载流插入

	ostream& operator<<(ostream& out, const string& s)
	{
		for (auto e : s)//遍历一个一个输出
		{
			out << e;
		}
		return out;






	}

有返回值是为了可以连续流插入

运算符重载流提取

版本一:

	istream& operator>>(istream& in, string& s)
	{
		
		char ch;

		
		in >> ch;//读取字符到ch
		while (ch != ' ' && ch != '\n')//读到‘ ’或‘\n’结束输入
		{s += ch;//将ch加进去
	    in >> ch;//循环读取


		}
		
return in;




	}

这样写会有一个问题,就是cin和scanf一样默认‘\n’和‘ ’是分割符不会进行读取,所以ch不会是空格或换行,所以陷入死循环.
在这里插入图片描述
版本2:
c语言中可以用getchar来读取,而c++中存在get就可以读空格

istream& operator>>(istream& in, string& s)
	{
		
		char ch;

		
		in.get(ch);
		
		
		while (ch != ' ' && ch != '\n')
		{

		
		
			s += ch;
			in.get(ch);


		}
		
			
			
		

		return in;




	}
	void test11()
	{
		string str1;
		string str2;
		cin >> str1;//>>str2;//>>str2;
		cout << str1;
		//cout << str1.capacity();




	}

在这里插入图片描述


版本3
由于我们在s+=ch,会出现频繁扩容,影响效率,我们应该怎么解决呢??
我们可以提前开好空间,但是不知道应该开多大.假如说我们开128个

	istream& operator>>(istream& in, string& s)
	{
		
		char ch;

		
		in.get(ch);
		
		s.reserve(128);

		while (ch != ' ' && ch != '\n')
		{

		
		
			s += ch;
			in.get(ch);


		}
		
			
			
		

		return in;




	}
	void test11()
	{
		string str1;
		string str2;
		cin >> str1;//>>str2;//>>str2;
		//cout << str1;
		cout << str1.capacity();




	}

在这里插入图片描述
两个数据开128就会有极大的浪费,多一点还好
在这里插入图片描述
版本4

	istream& operator>>(istream& in, string& s)
	{
		s.clear();//可能我们s里面之前有数据,但是流提取是要覆盖的

		char ch;

		ch = in.get();
		
		char buff[128];
		int i = 0;
		while (ch != ' ' && ch != '\n')
		{

			buff[i++] = ch;
			if (i == 127)
			{
				buff[127] = '\0';
				s += buff;
				i = 0;
			}
			ch = in.get();


		}
		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}

		return in;




	}

这里感觉可以类比冯诺依曼体系,buff就相当于内存,先将输入的值放在内存buff里面,等到装满了,在一次性给s,减少搬运次数.避免了一次空间开的很大,而数据只有几个
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

clear

	void clear()
		{
			_size = 0;
			_str[0] = '\0';

		}

c_str

将const string* 转化为const char*

	const char* c_str() const
		{
			return _str;



		}

cout不能直接处理自定义类型string,但是可以使用c_str将string转成常量字符串,内置类型就可以直接打印


源码

.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#include<assert.h>
#include<iostream>
#include<algorithm>
namespace zjw
{
	class string
	{
	public:
		typedef char* iterator;
		typedef   const char* const_iterator;
		iterator begin()
		{
			return _str;



		}
		iterator end()
		{
			return _str + _size;



		}
		const_iterator begin() const
		{
			return _str;



		}
		const_iterator end() const
		{
			return _str + _size;



		}
		string(const char* str = "")
			:_size(strlen(str))
		{
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
		~string()
		{
			delete[]_str;
			_str = nullptr;
			_size = _capacity = 0;





		}
		size_t size()
		{
			return _size;




		}
		size_t capacity()
		{
			return _capacity;


		}
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];



		}
		const char& operator[](size_t pos) const
		{
			assert(pos < _size);
			return _str[pos];



		}
		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[]_str;
				_str = tmp;
				_capacity = n;

			}





		}
		void push_back(char ch)
		{
			if (_capacity == _size)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);

			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';






		}
		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);

			}
			strcpy(_str + _size, str);
			_size += len;
			//_str[_size] = '\0';

		}
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;



		}
		string& operator+=(const char* str)
		{
			append(str);
			return *this;





		}
		void insert(size_t pos, char ch)
		{
			assert(pos <= _size);
			if (_capacity == _size)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);

			}
			size_t end = _size + 1;
			while (end > pos)
			{

				_str[end] = _str[end - 1];
				end--;


			}
			_str[pos] = ch;
			_size++;






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



		}
		void earse(size_t pos, size_t len = npos)
		{
			assert(pos < _size);
			if (len == npos || pos > _size - len)
			{
				_str[pos] = '\0';
				_size = pos;


			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;

			}







		}
		bool empty()
		{

			return _size == 0;

		}
		void resize(size_t n, char ch = '\0')
		{

			if (n <= _size)
			{
				_str[n] = '\0';
				_size = n;

			}
			else
			{
				reserve(n);
				for (size_t i = _size; i < n; i++)
				{
					_str[i] = ch;

				}
				_size = n;





			}






		}
		void insert(size_t pos, const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);

			}
			size_t end = _size + len;
			while (end > pos + len - 1)
			{
				_str[end] = _str[end - len];
				end--;

			}
			strncpy(_str + pos, str, len);
			_size += len;


		}
		size_t find(char ch, size_t pos = 0)
		{

			for (int i = pos; i < _size; i++)
			{
				if (_str[i] == ch)
					return i;



			}
			return npos;





		}
		size_t find(const char* sub, size_t pos = 0) const
		{
			assert(pos < _size);
			const char* ptr = strstr(_str + pos, sub);
			if (ptr != nullptr)
			{
				return ptr - _str;

			}
			else
			{
				return npos;
			}





		}
		string substr(size_t pos = 0, size_t len = npos) const
		{
			string substr;

			if (pos > _size - len)
			{
				for (int i = pos; i <= _size; i++)
				{
					substr += _str[i];
				}


			}
			else
			{

				for (int i = pos; i < pos + len; i++)
				{
					substr += _str[i];
				}
				substr += '\0';

			}
			return substr;





		}
		void swap(string& str)
		{
			std::swap(_str, str._str);
			std::swap(_size, str._size);
			std::swap(_capacity, str._capacity);





		}
		string(const string& s)
		{
			string tmp(s._str);
			swap(tmp);
		
		
		
		
		}
		string& operator=(string tmp)
		{
			swap(tmp);
			return *this;
		}
		string& operator=(const string& s)
		{
			char* tmp = new char[s._capacity + 1];
			strcpy(tmp, s._str);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
			return *this;

			




			

		}
		void clear()
		{
			_size = 0;
			_str[0] = '\0';

		}
		friend istream& operator>>(istream& in, string& s);
	public:
		static const int  npos;




	private:
		char* _str;
		int _size;
		int _capacity;



	};
	const int string::npos = -1;
	void swap(string& x, string& y)
	{
		x.swap(y);
		cout << "没使用库里的" << endl;
	
	}
	istream& operator>>(istream& in, string& s)
	{
		s.clear();

		char ch;

		ch = in.get();
		
		char buff[128];
		int i = 0;
		while (ch != ' ' && ch != '\n')
		{

			buff[i++] = ch;
			if (i == 127)
			{
				buff[127] = '\0';
				s += buff;
				i = 0;
			}
			ch = in.get();


		}
		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}

		return in;




	}
	//istream& operator>>(istream& in, string& s)
	//{
	//	
	//	char ch;

	//	
	//	in.get(ch);
	//	
	//	s.reserve(128);

	//	while (ch != ' ' && ch != '\n')
	//	{

	//	
	//	
	//		s += ch;
	//		in.get(ch);


	//	}
	//	
	//		
	//		
	//	

	//	return in;




	//}
	bool operator==(const string& s1, const string& s2)
	{
		return strcmp(s1.c_str(), s2.c_str())==0;



	}
	bool operator>(const string& s1, const string& s2)
	{
		return strcmp(s1.c_str(), s2.c_str());



	}
	bool operator<(const string& s1, const string& s2)
	{
		return  !(s1 > s2 && s1 == s2);



	}
	bool operator<=(const string& s1, const string& s2)
	{
		return  !(s1 > s2);



	}
	bool operator>=(const string& s1, const string& s2)
	{
		return  !(s1 < s2);



	}
	bool operator!=(const string& s1, const string& s2)
	{
		return  !(s1 == s2);



	}
	ostream& operator<<(ostream& out, const string& s)
	{
		for (auto e : s)
		{
			out << e;
		}
		return out;






	}
	//istream& operator>>(istream& in, string& s)
	//{
	//	s.clear();
	//	char ch;
	//	
	//	ch = in.get();
	//	//in >> ch;
	//	s.reserve(128);
	//	while (ch != ' ' && ch != '\n')
	//	{
	//		
	//		s += ch;
	//		ch = in.get();
	//		//in >> ch;

	//	}
	//	return in;
	//
	//
	//
	//
	//}
	void test1()
	{
		string str;
		str += 'a';

		str += 'b';
		str += "beijing";


		string::iterator it = str.begin();
		while (it != str.end())
		{
			cout << *it << " ";
			it++;

		}





	}
	void test2()
	{
		string str;
		str.push_back('a');
		str.push_back('a');
		str.push_back('b');
		str.push_back('a');
		str.push_back('a');
		string::iterator it = str.begin();
		while (it != str.end())
		{
			cout << *it << " ";
			it++;

		}
		cout << str[2];





	}
	void test3()
	{
		string str;
		str.append("stringbj");
		for (auto& e : str)
		{
			cout << e << " ";
		}


	}
	void print_string(const string it)
	{
		string::const_iterator res = it.begin();
		while (res != it.end())
		{
			cout << *res << " ";
			++res;



		}




	}
	void test4()
	{
		string str;
		str += "abc";
		str.append("stringbj");
		string::iterator it = str.begin();
		while (it != str.end())
		{
			cout << *it << " ";
			it++;

		}
		//str.insert(0, 'g');
		for (auto& e : str)
		{
			cout << e << " ";
		}
		cout << endl;
		// str.earse(1,string::npos);*/
		/* for (auto e : str)
		 {
			 cout << e << " ";
		 }*/
		 // print_string(str);



	}
	void test5()
	{
		string str;
		str.push_back('a');
		str.push_back('a');
		str.push_back('b');
		str.resize(10);
		/* string::iterator it = str.begin();
		 while (it != str.end())
		 {
			 cout << *it << " ";
			 it++;

		 }*/
		cout << str.c_str();







	}
	void test6()
	{
		string str;
		str.push_back('a');
		str.push_back('a');
		str.push_back('b');
		str.insert(2, "hello");
		cout << str.c_str();




	}
	void test7()
	{
		string str;
		str.push_back('a');
		str.push_back('a');
		str.push_back('b');
		str.insert(2, "hello");
		cout << endl;
		int ret = str.find('b', 0);
		cout << ret;


	}
	void test8()
	{
		string str;
		str += "beijing huanyingni zhangjiawang";
		int ret = str.find("zhangjiawang");
		cout << ret;




	}
	void test9()
	{
		string str;
		str += "beijing huanyingni zhangjiawang";
		string op = str.substr(0, 10);
		cout << op.c_str();




	}
	void test10()
	{
		string str1;
		string str2;
		str1 += "abc";
		str2 += "aba";

		cout << (str1 == str2) << endl;
		cout << ("aba" == str2) << endl;
		cout << (str2== "aba") << endl;
		 cout << (str1>str2) << endl;
		 cout << (str1 >=str2) << endl;
		 cout << (str1<str2) << endl;
		 cout << (str1 <=str2) << endl;
		 cout << (str1!=str2) << endl;




	}
	void test11()
	{
		string str1;
		string str2;
		cin >> str1;//>>str2;//>>str2;
		//cout << str1;
		cout << str1.capacity();




	}
	void test12()
	{   string str1;
		string str2;
		str1 += "hello";
		str2+="nihao";
		cout << "str1:"<<str1 << endl;
		cout << "str2:"<<str2 << endl;
		str1.swap(str2);
		cout << "str1:" << str1 << endl;
		cout << "str2:" << str2 << endl;

	}
	void test13()
	{
		string str1;
		string str2;
		str1 += "hello";
		str2 += "nihao";
		cout << "str1:" << str1 << endl;
		cout << "str2:" << str2 << endl;
		swap(str1, str2);
		cout << "str1:" << str1 << endl;
		cout << "str2:" << str2 << endl;
	
	
	}
	void test14()
	{
		
		string str2;
		
		str2 += "nihao";
		string str1(str2);
	
	
	
	}
	
}
	

.cpp

#include"标头.h"

int main()
{
  zjw::test11();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/443519.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于机器学习的网络入侵检测二元分类模型构建与性能评估(NSL-KDD数据集)

简介 该项目是一个基于NSL-KDD数据集的网络入侵检测系统&#xff0c;主要采用机器学习方法对网络流量数据进行使用了多种机器学习模型&#xff0c;如逻辑回归、线性SVM、多项式核SVM、高斯核SVM、决策树、随机森林、朴素贝叶斯和K近邻算法训练二元分类&#xff08;正常/异常&a…

漫谈技术成长

引言 相信很多程序员在自己的技术成长之路上&#xff0c;总会遇到许许多多的难关&#xff0c;有些难关咬咬牙就过去了&#xff0c;而有点难关则需要有一定的能力&#xff0c;才能克服。因此&#xff0c;本文主要围绕“技术成长” 话题&#xff0c;为何会选择技术方向&#xff0…

数据结构从入门到精通——队列

队列 前言一、队列1.1队列的概念及结构1.2队列的实现1.3队列的实现1.4扩展 二、队列面试题三、队列的具体实现代码Queue.hQueue.ctest.c队列的初始化队列的销毁入队列出队列返回队头元素返回队尾元素检测队列是否为空检测元素个数 前言 队列是一种特殊的线性数据结构&#xff…

练习ROS动作编程

ROS学习记录&#xff1a;动作编程 引言&#xff1a; ​ 通过本实验&#xff0c;我们将联系我们学过的动作编程&#xff0c;客户端发送一个运动目标,模拟小乌龟运动到目标位置的过程,包含服务端和客户端的代码实现&#xff0c;并且带有实时的位置反馈。 希望你在本次学习过后&am…

计算机网络谢希仁第8版课后习题答案(PDF)

百度网盘&#xff1a;https://pan.baidu.com/s/1cY_DkwaljjL7kU00-APLhw 提取码&#xff1a;5488

linux网络通信(TCP)

TCP通信 1.socket----->第一个socket 失败-1&#xff0c;错误码 参数类型很多&#xff0c;man查看 2.connect 由于s_addr需要一个32位的数&#xff0c;使用下面函数将点分十进制字符串ip地址以网络字节序转换成32字节数值 同理端口号也有一个转换函数 我们的端口号位两个字…

Spring boot 请求参数包含[]等特殊字符,导致无法接收问题

前言对字符进行转义修改tomcat 配置 前言 Spring boot 请求参数包含[]等特殊字符&#xff0c;导致无法接收问题 对字符进行转义 中括号[] 必须用%5B%5D转义&#xff0c;否则tomcat无法解析&#xff0c;回抛出不合法字符异常&#xff0c;不会进入控制器 修改tomcat 配置 p…

Kubernetes 安全秘籍:5 个你必须知道的知识点

Kubernetes 安全和身份验证是确保集群和应用安全的关键。今天将深入探讨 Service Account、身份验证和RBAC的关键概念和实践&#xff0c;帮助您构建安全可靠的应用。今天本文将着重于安全相关的内容&#xff0c;并提供更详细的示例和配置说明&#xff0c;帮助兄弟们更深入地理解…

Java8 CompletableFuture异步编程-进阶篇

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前言 我们在前面文章讲解了CompletableFuture这个异步编程类的基本用法&#xff0c;…

猫头虎分享已解决Bug || 系统监控故障:MonitoringServiceDown, MetricsCollectionError

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【敬伟ps教程】文字处理工具

文章目录 文字工具使用方式文字图层文字工具选项字符面板段落面板文字工具使用方式 文字工具(快捷键T),包含横排和直排两种类型 创建文本两种类型:点式文本、段落文本 创建文字方式 1、在画面上单击,出现文字光标,可输入文字,然后需要在工具栏中点击“√”或者 Ctrl+…

存算一体成为突破算力瓶颈的关键技术?

大模型的训练和推理需要高性能的算力支持。以ChatGPT为例&#xff0c;据估算&#xff0c;在训练方面&#xff0c;1746亿参数的GPT-3模型大约需要375-625台8卡DGX A100服务器训练10天左右&#xff0c;对应A100 GPU数量约3000-5000张。 在推理方面&#xff0c;如果以A100 GPU单卡…

UnityShader——09数学知识3

方阵 行与列数量相等的矩阵,n*n阶矩阵 对角矩阵 当对角线以外的矩阵内元素全为0&#xff0c;则称之为对角矩阵&#xff0c;对角矩阵的前提是必须是方阵 单位矩阵 对角线元素全为1&#xff0c;其余元素全为0&#xff0c;属于对角矩阵的一部分 矩阵和向量 把1 * n阶矩阵称…

JavaWeb - 2 - HTML、CSS

什么是HTML、CSS&#xff1f; HTML&#xff08;HyperText Markup Language&#xff09;&#xff1a;超文本标记语言 超文本&#xff1a;超越了文本的限制&#xff0c;比普通文本更强大&#xff0c;除了文字信息&#xff0c;还可以定义图片、音频、视频等内容 标记语言&…

ESP8266程序烧录方法(以ESPFlashDownloadTool为例)

0 工具准备 ESP8266必须包含的目标bin ESPFlashDownloadTool_v3.6.3.exe NodeMCU&#xff08;ESP8266&#xff09; sscom5 1 ESP8266程序烧录方法&#xff08;以ESPFlashDownloadTool为例&#xff09; 1.1 生成ESP8266所需的bin文件 可以参考前面所写的《安信可IDE&#xff0…

被唤醒的“第二十条”深入人心

近来张艺谋执导的电影《第二十条》&#xff0c;因为它与正在召开中的全国两会所发布的《最高人民法院工作报告》联系相当紧密&#xff0c;加之可免费收看&#xff0c;网民便相互转告&#xff0c;于是此信息条目立即冲上了网络热搜榜&#xff0c;观者如潮。因为最高人民法院工作…

STM32 HAL库RTC复位丢失年月日的解决办法

STM32 HAL库RTC复位丢失年月日的解决办法 0.前言一、实现方式1.CubeMX配置&#xff1a;2.MX_RTC_Init()函数修改2.编写手动解析函数 二、总结 参考文章&#xff1a;stm32f1 cubeMX RTC 掉电后日期丢失的问题 0.前言 最近在使用STM32F103做RTC实验时&#xff0c;发现RTC复位后时…

LeetCode-Hot100

哈希 1.两数之和&#xff1a; 给定一个整数数组nums和一个整数目标值target&#xff0c;请你再该数组中找出和为目标值target的那两个整数&#xff0c;并返回它们的数组下标。 思路&#xff1a;暴力解法是使用两层循环来遍历每一个数&#xff0c;然后找出两数之和等于target的…

2024/3/9d打卡整数划分---背包动态规划方式,计数类动态规划

目录 题目 DP分析 第一种方法&#xff0c;背包DP 代码 第二种方法&#xff08;有点难想到&#xff09; 代码 题目 一个正整数 n 可以表示成若干个正整数之和&#xff0c;形如&#xff1a;nn1n2…nk&#xff0c;其中 n1≥n2≥…≥nk,k≥1。 我们将这样的一种表示称为正整数 …

maven项目引入私有jar,并打包到java.jar中

私有jar存放位置 maven依赖 <dependency><groupId>com.hikvision.ga</groupId><artifactId>artemis-http-client</artifactId><version>1.1.10</version><scope>system</scope><systemPath>${project.basedir}/s…