7

为什么对字符串参数的 const 引用可以采用字符串文字?字符串文字,如"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& strconst 引用而不是 const 引用组成,以便将文字用于构造str?

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

4

3 回答 3

9

当你这样做

result.doSomething("asdas");

编译器查看您是否有 adoSomething(const char[]);并且什么也没找到。由于没有合适的函数,因此它会尝试找到一个重载,该重载采用可以从 a 构造的内容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;
}
于 2017-05-22T19:19:39.283 回答
4

字符串文字,如“hello”,不是变量

术语“变量”的定义非常模糊,并没有任何具体概念的真正支持。

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

您缺少的是“中间步骤”,即std::string从该文字构造一个临时的,然后通过绑定到 ref-to- 来扩展其生命周期const

所以,伊什:

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

阅读有关隐式转换的更多信息。

于 2017-05-22T19:30:15.047 回答
1

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

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

于 2017-05-22T19:14:20.003 回答