通过转换构造函数初始化const引用时会发生什么?它和普通的任务有什么不同吗?看看这段代码:
void func(const char* cstr) {
std::string S1 = cstr;
const std::string& S2 = cstr;
}
S1和S2之间有什么实际区别吗?你为什么要使用第二个表达式?
答案 0 :(得分:1)
S1和S2之间是否存在实际差异?
在表现方面,答案是否定的。两条指令都调用转换构造函数并分配内存,然后将char
数组复制到std::string
实例的内部动态内存中。
在语法方面,答案显然是const
- ness:在函数的连续块中,S2
处理的对象无法修改。
答案 1 :(得分:1)
使用std::string S1 = cstr;
S1
是一个临时移动构造的。这种移动构造应该被省略,但应该是可以访问的。由于不是const
,因此可以修改S1
。
使用const std::string& S2 = cstr;
S2
是对临时字符串的const引用,具有延长的生命周期。由于const
,S2
无法修改。
对于没有移动/复制构造函数的类型
struct S {
S() = default;
S(const S&) = delete;
S& operator =(const S&) = delete;
};
您可以使用第二种形式,但不能使用第一种形式:
S s1 = S{}; // Invalid
const S& s2 = S{}; // Valid
S&& s3 = S{}; // Valid too.
答案 2 :(得分:0)
您获得对S1字符串的const
引用,编译器会强制执行该值的const
。如果您尝试修改S2
,则无法编译。对于局部变量,它没有多大意义,除非您不相信自己不修改S2
,或者当您正在进行代码重构时移动事物并且您希望确保S2
永远不会改变。
但是如果你将一个字符串作为参数传递给一个函数,你可以使用const
引用来避免昂贵的副本:
void f(const std::string& S2) { ... }
const
通常无法帮助编译器对代码执行优化,因为您始终可以使用const_cast
删除变量的const
。