在C语言中只能通过字符串数组来模拟字符串,没有字符串类型。在C++引入了string类来表示字符串类型。从而用它定义字符串。
在C语言中:
char str[] = "abc";
char str[] = {'a','b','c','\0'};
char* str = "abc";
//这三种形式是C语言下用来表示字符串的方式。
而在C++语言下:
string str1;//调用无参构造,生成一个空字符串对象,strlen(str) = 0;
string str1 = "";//调用有参构造,虽然作用相当于上面的,生成一个空字符串对象。等价于string str1("");
string str2 = "abc";//调用有参构造
string str3("abc");//调用有参构造
string str4 = string("abc");//调用有参构造
string str5 = str4;//调用拷贝构造
string str6(str5);//调用拷贝构造
//以上这种方式都是定义字符串string类的对象。
注意
: “” 即空字符串也是一个字符串字面值,也会被存储到静态存储区只存一份实例。
string类是基于模板的。是basic_string类的别名。
string类里有以下三个常用到的构造函数:
string(){_data = new char[1]; _data[0]='\0';};//无参构造
string(const char * str){//有参构造_data = new char[sizeof(str)];for(int i = 0; i < sizeof(str);i++){_data[i] = str[i];}
};
string(const string & str){//拷贝构造_data = new char[strlen(str)+1];strcpy(_data,str);
};
C++中的string类底层存储字符串的原理是,存储一个 char * 类型的成员指针变量(如上述构造函数中的_data)。
而 char * 类型的指针变量 会指向一块堆内存。在堆内存中存储字符串内容。当string类对象生命周期结束时,会调用 其析构函数,delete 掉 char *类型的指针变量。释放存储字符串内容的堆内存。
注意
:string对象中的字符串实际是存储于堆内存中的。何时会释放掉这块堆内存,只要string类的对象的声明周期结束即将时,它会自动调用string类的析构函数,来释放成员变量_data所指向的那块堆内存。
拷贝构造函数的调用机制,是必须根据当前已有的一个对象来对另一个新对象进行拷贝赋值。
下面说一下:
字符串的引用类型的使用
string & refstr = "abc";//编译不过,“abc” 不是左值
const string & refstr = "abc";//可以,会根据string的有参构造函数生成一个匿名对象。然后refstr就是这个匿名对象的别。通过refstr来访问匿名对象的地址。等价于 const string & refstr = string("abc");
如果想这个样单独的一条语句string("abc");//匿名对象,这一行表达式语句执行完毕后,string对象的生命周期就结束了。
那么像上面那样 refstr可以延迟这个匿名对象生命周期。直到refstr引用变量的声明周期结束后,那个匿名对象的声明周期也就结束了。
void func(const string & refstr){............
}string str = "abc";
func(str);//这种方式传参不存在对象创建。通过 refstr 来访问 str内容。
func("abc");//这种方式传参存在一次调用有参构造创建string类型的匿名对象。相等于func(string("abc"));通过refstr来访问这个匿名对象。