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

时间:2016-11-08 00:52:57

标签: c++ string initialization

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'请求&#34 ;.

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

1 个答案:

答案 0 :(得分:6)

你的书很旧,但基本上是正确的 [1] 。请注意,"Jane Doe"不是std::string,而是const char[9](可能会衰减到const char*)。因此,对于CStr name3 = "Jane Doe";,需要两个用户定义的转换(即const char* - > std::stringstd::string - > CStr),这不是允许一个implicit conversion

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

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

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

或直接使用string literal(自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评论的那样,direct initialization(即CStr name3("Jane Doe")CStr name3{"Jane Doe"}(因为C ++ 11))可以正常工作,而CStr name3 = "Jane Doe";copy initialization ,他们在某些方面有所不同:

  

此外,复制初始化中的隐式转换必须   直接从初始化器产生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 Doeconst char*)必须直接转换为CStr;因为需要两个用户定义的转换,所以代码被拒绝。对于直接初始化,可以将Jane Doeconst char*)转换为CStr的构造函数的参数,即首先std::string,然后CStr::CStr(std::string)将是调用来构造对象。

[1] "Jane Doe"是一个c风格的string literal,它是const,从C ++ 11开始,将它分配给char*是非法的,例如

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