通过转换构造函数初始化const引用时会发生什么?

时间:2016-08-30 09:12:02

标签: c++

通过转换构造函数初始化const引用时会发生什么?它和普通的任务有什么不同吗?看看这段代码:

void func(const char* cstr) {
    std::string S1 = cstr;
    const std::string& S2 = cstr;
}

S1和S2之间有什么实际区别吗?你为什么要使用第二个表达式?

3 个答案:

答案 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引用,具有延长的生命周期。由于constS2无法修改。

对于没有移动/复制构造函数的类型

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