为什么对字符串参数的常量引用可以采用字符串文字?

Why can a const reference to a string parameter take string literals?

本文关键字:字符串 文字 引用 参数 常量 为什么      更新时间:2023-10-16

为什么对字符串参数的常量引用可以采用字符串文字?字符串文字,如"hello",不是变量,那么为什么这段代码有效呢?

class CVector {
public:
int x, y;
CVector() {};
~CVector() { delete ptr; }
string* ptr;
void doSomething(const string& str) { ptr = new string(str); }
void print() { cout << "n" << *ptr; }
};
int main()
{
result.doSomething("asdas");
result.print();
return 0;
}

首先,我认为引用作为参数用于避免复制过程并直接访问作为参数的变量(不过我仍然可以正确)。但是字符串文字"asdas"不是变量,那么为什么参数可以把字符串文字作为参数呢?我的意思是,由于参数str是一个引用,它将成为该实体的别名,对吧?如果是这样,文字是否只是变成了一个变量?

参数列表不应该由string& str而不是常量引用组成,以便文字将用于str的构造?

只要引用处于活动状态,常量引用就不会使引用的实体保持活动状态吗?如果是这样,你为什么要对文字这样做?

当你这样做时

result.doSomething("asdas");

编译器会查看您是否有doSomething(const char[]);,但什么也没找到。 由于没有合适的函数,它然后尝试找到一个重载,该重载需要可以从const char[]构造的东西,并找到doSomething(const string& str)。 由于编译器允许进行一个用户定义的转换,因此它从字符串文字构造一个临时std::string,并通过引用 const 将该临时传递给函数。

参数列表不应该由string&str而不是const引用组成,以便在str的构造中使用文字吗?

不,这仅适用于对 const 的引用,不适用于常规引用,因为常规引用无法绑定到临时引用。

只要引用处于活动状态

,常量引用就不会使引用的实体保持活动状态吗?如果是这样,你为什么要对文字这样做?

仅当对象是函数本地对象时,对 const 的引用才会延长对象的生存期。 在函数的作用域内,对象将处于活动状态,因为调用该函数的表达式尚未结束,但是如果您要尝试保留对类中std::string的引用,则不起作用。

有效地将代码转换为

int main()
{
CVector result
{
std::string temp = "asdas";
result.doSomething(temp);
}
result.print();
return 0;
}

字符串文字,如"hello",不是变量

术语"变量"的定义非常模糊,没有任何具体概念的支持。

表达式"hello"表示具有无法修改的静态存储持续时间的对象。像任何其他表达式一样,它可能用于初始化其他对象。在本例中,您将使用表达式初始化std::string(在其衰减为const char*之后)。

您缺少的是"中间步骤",即从该文字构造临时std::string,然后通过绑定到引用const来延长其生命周期。

所以,ish:

const std::string temp{"Hello world"};   // the compiler creates this transparently
const std::string& ref = temp;  // this is yours, and it extends temp's life

有关详细信息,请阅读隐式转换

std::string有一个隐式const char *转换构造函数。

编译器被允许进行一次隐式转换以使类型匹配,因此它使用所述 ctor 将const char *转换为临时std::string,并且从那里开始一帆风顺,因为const&(常量左值引用)被允许绑定到临时(并延长它们的生命周期)。