为什么这个C++成员初始化列表不起作用?

Dra*_*utX 2 c++ string initialization

C++ in Plain English,Second Edition(1999)中,书中有一节说"="可用于在调用正确的构造函数时进行初始化.就像给定一个类CStr和一个构造函数一样CStr(char*),本书说:

类似地,最后的声明调用构造函数CStr(char*):

CStr name3 = "Jane Doe";
Run Code Online (Sandbox Code Playgroud)

我想用std::string构造函数尝试相同的东西.我的测试代码的一部分是这样的:

using namespace std;
class CStr {
private:
    string name;
public:
    CStr(string s): name(s) {}
};

int main() {
    CStr name3 = "Jane Doe";
}
Run Code Online (Sandbox Code Playgroud)

但是,当我编译时,我在name3初始化中遇到错误:

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

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

son*_*yao 6

你的书很旧,但基本上是正确的[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");
Run Code Online (Sandbox Code Playgroud)

或直接使用字符串文字(自C++ 14),其类型为std::string:

CStr name3 = "Jane Doe"s;
Run Code Online (Sandbox Code Playgroud)

为什么没有将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
Run Code Online (Sandbox Code Playgroud)

这意味着,对于复制初始化,参数Jane Doe(即a const char*)必须CStr直接转换为; 因为需要两个用户定义的转换,所以代码被拒绝.对于直接初始化,将convert 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
Run Code Online (Sandbox Code Playgroud)

  • 或者`CStr name3("Jane Doe")`或`CStr name3 {"Jane Doe"}` (2认同)