使用字符串文字构造对象

Kam*_*dan 8 c++ string constructor initialization string-literals

我有以下课程:

#include <iostream>
#include <string>

using namespace std;

class CLS
{
   int value;
   string str_value;

public:

    CLS(int param) { value = param; }

    CLS(string param)
    {
       str_value = param;
    }
};

int main()
{
    CLS a(2);
    CLS b = 3;
    CLS c("4");
    CLS d = "5";  // Error: invalid conversion from 'const char*' to 'int'
}
Run Code Online (Sandbox Code Playgroud)

我搜索了没有运气的错误原因.

用字符串文字构造是否正确?如果不是,为什么?如果是的话,我的代码出了什么问题?

我使用gcc 5.3与Code :: Blocks 16.1.

son*_*yao 11

起初,"4"不是std::string,它是const char[2].然后

CLS c("4");直接初始化,CLS将检查构造函数进行初始化c.CLS::CLS(string)在这里被选中,因为const char[]可以std::string通过用户定义的转换(即通过std::string::string(const char*))隐式转换.

CLS d = "5";复制初始化,

(强调我的)

  • 如果T是类类型,并且类型的cv-nonqualified版本other不是T或派生自T,或者如果T是非类类型,但类型other是类类型,则可以从类型转换的用户定义转换序列的otherT(或从衍生的类型T,如果T是一个类类型和一个转换功能是可用的)进行检查和最好的一个是通过重载解析选择.

这意味着用户定义的转换序列需要转换const char[2]CLS.甚至const char[]可以转换为std::string,并且std::string可以转换为CLS,但在一个隐式转换序列中只允许一个用户定义的转换.这就是它被拒绝的原因.

(强调我的)

隐式转换序列按以下顺序包含以下内容:

1)零个或一个标准转换序列;
2)零或一个用户定义的转换;
3)零个或一个标准转换序列.

顺便说一句:如果你把它改为std::string明确地用作初始化表达式,它就可以正常工作.例如

CLS d = std::string{"5"};  // pass a temporary std::string constructed from "5" to the constructor of CLS

using namespace std::string_literals;
CLS d = "5"s;              // "5"s is a string literal of type std::string (supported from C++14)
Run Code Online (Sandbox Code Playgroud)


Dan*_*our 8

CLS a(2); 
CLS b = 3;
CLS c("4");
CLS d = "5";
Run Code Online (Sandbox Code Playgroud)

ac通过直接初始化进行初始化.bd在另一方面使用拷贝初始化.

区别在于,对于复制初始化,编译器从(在某种情况下d)char const *(这有点不准确,请参见答案结束)中搜索(单个)用户定义的转换CLS,而对于直接初始化,尝试所有构造函数,其中CLS(std::string)可以是因为有std::string(char const *)可用的转换而使用.

详情:

"5"是(C)字符串文字.它的类型是char const [2].首先,搜索用户定义的从该类型的转换CLS.因为没有被发现,从标准转换Type[N]Type *(有Type= char constN= 2)被施加,导致char const *.然后编译器尝试从中查找用户定义的转换CLS.因为它找不到一个,并且没有更多的标准转换它可以尝试,编译失败.