字符串

C 语言中的字符串

C 语言中字符串就是一个字符数组,通常使用const char*表示,但是相较于字符数组,字符串会在最后一个元素添加终止符\0,在输出字符串时知道在何处结束

#include <iostream>
const char* name = "ZhangSan";
char name2[8] = {'Z','h','a','n','g','S','a','n'};
char name3[9] = {'Z','h','a','n','g','S','a','n','\0'};
char name4[9] = {'Z','h','a','n','g','S','a','n',0};
 
std::cout << name << std::endl;   //ZhanSan
std::cout << name2 << std::endl;  //ZhanSan....未知字符
std::cout << name3 << std::endl;  //ZhanSan
std::cout << name4 << std::endl;  //ZhanSan

上述代码中name2会在内存中一直找到终止符后停止输出,因此在输出的末尾会出现未知字符。如果在字符数组最后增加终止符(或者对应的 ASCII 码)即可正确输出

C++中的字符串

在 C++中使用双引号包裹的多个字符本质上是const char*,在字符串赋值时会通过char*的隐式转换成为字符串

#include<iostream>
#include<string>
 
std::string name = "ZhangSan";     //“ZhangSan”其实是const char*
std::cout << name << std::endl;

头文件<iostream>中已经包含 string 的定义,可以直接使用。但是输出字符串时,未导入头文件<string>会出现错误,提示无法输出字符串到流中,因为<<操作符关于字符串操作的重载是在<string>中实现的。

C 语言中处理字符数组const char*的函数strlenstrcpy等函数均可在 C++的字符串中找到对应的函数

std::string name = "ZhangSan" + " hello!";              //ERROR
std::string name = "ZhangSan";
name += " hello!";                                      //OK
std::string name = std::string("ZhangSan")+" hello!";   //OK
std::cout << name << std::endl;

不可以直接将两个字符串常量相加,因为两个字符串常量其实是const char*,因此两个指针相加是错误操作。正确的字符串拼接方式是拆分成两步,将字符串变量与const char*相加,因为+操作被<string>重载后,可以进行字符串与字符数组指针相加操作

// 使用值传递会出现字符串复制,影响程序性能
void PrintString(std::string str){
	std::cout << string << std::endl;
}
//应使用引用传递,并且保证string不可修改
void PrintString(const std::string& str)
{
	std::cout << string << std::endl;
}

隐式转换与 explicit 关键字

//类定义
class Entity
{
private:
    std::string m_Name;
    int m_Age;
public:
    Entity(std::string name):m_Name(name),m_Age(-1){}
    Entity(int age):m_Name("Unknown"),m_Age(age){}
};
 
void printEntity(const Entity& entity){}

隐式转换

类中定义只有一个参数的构造函数时,可以使用如下操作实例化对象

Entity a = 22;            //等价Entity(22)
Entity b = "ZhangSan";    //等价Entity("ZhangSan")

在上述操作中存在着一次隐式转换,即Entity a = Entity(22) = 22,但是隐式转换仅调用一次

printEntity(22);                 //OK
printEntity("ZhangSan");         //ERROR
printEntity(Entity("ZhangSan"))  //OK

Zhangsan属于 char 型数组,需要经历两次转换,第一次char型数组=>string,第二次string=>Entity,所以出现执行错误

explicit 关键字

在构造函数前面增加explicit关键字可以禁止上述的隐式转换,避免出现未知的类型转换,只能通过显式构造函数实例化对象,使得代码更加清晰