我正在审查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对象?否则,就复制构造函数/赋值调用而言,这里到底发生了什么?
答案 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"
到decaying到const 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 &
。