了解对非成本数据成员的const引用的分配

时间:2017-01-05 07:42:38

标签: c++

我正在审查C ++引用,试图解释为什么以下代码符合:

#include <string>

class Foo {

public:

    Foo(const std::string& label)
        : d_label(label) {}

private:

    std::string d_label;

};

int main(int argc, const char** argv) {
    Foo("test");
    return 0;
}

这里,我们将const字符串的引用分配给字符串。这样做是label的副本是非const?如果是这样,为什么我们可以复制一个本身非const的const对象?否则,就复制构造函数/赋值调用而言,这里到底发生了什么?

3 个答案:

答案 0 :(得分:3)

在C ++中,关键字const实际上意味着只读。要创建对象的副本,您不需要写访问权限。因此,您可以将const std::string复制到std::string

另请注意,在C ++中复制意味着默认情况下进行深层复制。这称为值语义。因此,操纵复制的字符串将不会对原始字符串执行任何操作。

现在回答你的最后一个问题:以下一行是怎么回事?

Foo("test");

"test"的类型为const char[5]。编译器搜索Foo的匹配构造函数。由于"test"可通过

隐式转换为std::string
basic_string<CharT,Alloc>::basic_string( const CharT * s, const Alloc & a = Alloc() );

构造函数,将执行此转换,i。即临时std::string"test"构成。然后将对此临时值的const引用传递给构造函数

Foo::Foo( const std::string & label );

这个构造函数依次调用std::string的复制构造函数来构造d_label的{​​{1}}成员:

Foo

答案 1 :(得分:1)

此处不会发生作业d_label(label) 使用d_label初始化变量label,随后最终调用string类型的copy constructor

让我们仔细看看:

  • Foo("test");使用const std::string& label初始化"test",其类型为const char[5]

  • 此处使用类型为label的值初始化字符串引用(const char[5])。此初始化有效,因为"test"decayingconst char *可以传递给获得string的{​​{1}}个构造函数之一。

  • 现在const char *是对存储label的真实字符串对象的引用。
  • 然后,"test"使用d_label(label)引用的对象初始化Foo::d_label
  • 此时调用label类型的复制构造函数并构造string

答案 2 :(得分:1)

C ++提供了引用语义和值语义:对象具有值,然后您可以引用对象。

std::string d_label

d_label是一个包含字符串值的对象。它被认为拥有保存字符串的字节作为内存资源。所有权概念合理化使用d_label作为修改字符串的接口。

const std::string& label

label是对字符串的只读引用。这与“对const字符串的引用不完全相同。”它指的是一个可能(可能不是)const的对象。

: d_label(label)

使用复制构造函数初始化d_label,内容为label。然后,您可以使用副本执行您喜欢的操作。您知道复制过程不会修改label的基础对象,因为label已声明为const &