为什么这个c++成员初始化列表不能工作?

Why does this C++ member initializer list not work?

本文关键字:列表 不能 工作 初始化 成员 c++ 为什么      更新时间:2023-10-16

c++ In Plain English, Second Edition(1999)中,书中有一节说可以使用"="在调用正确的构造函数时进行初始化。就像给定一个类CStr和一个构造函数CStr(char*),书上是这样说的:

类似地,最后一个声明调用构造函数CStr(char*):
CStr name3 = "Jane Doe";

我想用std::string构造函数尝试同样的事情。我的部分测试代码是这样的:

using namespace std;
class CStr {
private:
    string name;
public:
    CStr(string s): name(s) {}
};
int main() {
    CStr name3 = "Jane Doe";
}
但是,当我编译时,在name3初始化中得到一个错误:

"请求从'const char[9]'转换为'CStr'非标量类型"。

为什么不将CStr::name初始化为字符串s = "Jane Doe"工作?像string nameTest{"Jane Doe"};这样的字符串测试工作了,所以我认为这也会起作用。也许这本书太旧了(这是我现在唯一的一本书),但我认为错误更多的是在我身上。

你的书很旧,但基本上是对的[1]注意,"Jane Doe"不是std::string,而是const char[9](并且可能衰减到const char*)。因此对于CStr name3 = "Jane Doe";,需要进行两次用户定义的转换(即const char* -> std::stringstd::string -> CStr),这在一次隐式转换中是不允许的。

这也证明了如果CStr的构造以const char*作为参数,CStr name3 = "Jane Doe";也可以正常工作,因为它只需要进行一次用户定义的转换。

您可以通过添加显式转换来减少一个:

CStr name3 = std::string("Jane Doe");

或直接使用字符串字面值(c++ 14起),其类型为std::string:

CStr name3 = "Jane Doe"s;

为什么不将CStr::name初始化为字符串s = "Jane Doe"工作?像string nameTest{"Jane Doe"};这样的字符串测试可以工作,所以我认为这也可以工作。

你的问题不够清楚,无论如何,std::string nameTest{"Jane Doe"};工作是因为,(取决于你的误解,)(1)这里只需要一个隐式转换(const char* -> std::string;(2) string nameTest{"Jane Doe"};为直接初始化。

正如@LightnessRacesinOrbit评论的那样,直接初始化(即CStr name3("Jane Doe")CStr name3{"Jane Doe"}(自c++ 11起))可以正常工作,而CStr name3 = "Jane Doe";是复制初始化,它们在某些方面有所不同:

此外,复制初始化中的隐式转换必须直接从初始化式生成T,而,例如类型进行隐式转换T的构造函数参数的初始化式

struct S { S(std::string) {} }; // implicitly convertible from std::string
S s("abc"); // OK: conversion from const char[4] to std::string
S s = "abc"; // Error: no conversion from const char[4] to S
S s = "abc"s; // OK: conversion from std::string to S

这意味着,对于复制初始化,实参Jane Doe (const char*)必须直接转换为CStr;因为需要两次用户定义的转换,所以代码被拒绝。对于直接初始化,可以将Jane Doe (const char*)转换为CStr的构造函数的参数,即先转换为std::string,然后再调用CStr::CStr(std::string)来构造对象。


[1] "Jane Doe"是一个C风格的字符串字面值,它是const,从c++ 11开始,将它赋值给char*是非法的,例如

char * pc = "Jane Doe";         // illegal
const char * pcc = "Jane Doe";  // fine