我回答了here https://stackoverflow.com/questions/587070/c-constructor-syntax/587116#587116
我在这里的答案中加入了一件事:也不使用任何赋值运算符.
不过,对字符串特定事物的简短解释。std::string
有一个构造函数接受一个参数char const*
:
// simplified to a normal class declaration. std::string actually
// is a template instantiation.
class string {
public:
string(char const* str) {
// copy over...
}
};
现在您可以看到它有一个构造函数,它带有一个指向字符的指针。这样它就可以接受字符串文字。我认为以下情况是显而易见的:
string s("hello");
它会直接调用构造函数并初始化s
从而。这就是所谓的直接初始化.
初始化变量的另一种方法称为复制初始化。标准规定,对于复制初始化的情况,初始化器具有not它正在初始化的对象的类型,初始化程序将转换为正确的类型。
// uses copy initialization
string s = "hello";
首先我们先来说一下类型
-
s
具有 std::string 类型
-
"hello"
是一个数组,在这种情况下再次像指针一样处理。因此我们将其视为char const*
.
编译器会寻找两种方法来进行转换。
- 有没有转换构造函数在 std::string 中?
- 初始化器的类型是否具有返回 a 的转换运算符函数
std::string
?
它将创建一个临时的std::string
通过其中一种方法来初始化对象s
通过使用std::string
's 复制构造函数。它看到std::string
has接受初始值设定项的转换构造函数。所以它使用它。最后,它实际上与
std::string s(std::string("hello"));
请注意,您的示例中使用的表单触发了所有这些
std::string s = "hello";
定义一个隐式转换。您可以将构造函数标记为char const*
as explicit对于您的类型,如果您想知道您的东西的初始化规则,并且它不允许使用相应的构造函数作为转换构造函数不再:
class string {
public:
explicit string(char const* str) {
// copy over...
}
};
这样,使用初始化它copy initialization
and a char const*
实际上现在已经被禁止了(以及在其他地方)!
现在,如果编译器不支持在各个地方省略临时变量。编译器可以假设复制构造函数copies在这种情况下,可以消除临时字符串的额外副本,而是直接将临时 std::string 构造到初始化对象中。但是,复制构造函数必须特别可访问。所以,如果这样做的话,复制初始化是无效的
class string {
public:
explicit string(char const* str) {
// copy over...
}
private: // ugg can't call it. it's private!
string(string const&);
};
现在实际上,只有直接初始化的情况才有效。