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是类类型,则可以从类型转换的用户定义转换序列的other到T(或从衍生的类型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)
CLS a(2);
CLS b = 3;
CLS c("4");
CLS d = "5";
Run Code Online (Sandbox Code Playgroud)
a并c通过直接初始化进行初始化.b而d在另一方面使用拷贝初始化.
区别在于,对于复制初始化,编译器从(在某种情况下d)char const *(这有点不准确,请参见答案结束)中搜索(单个)用户定义的转换CLS,而对于直接初始化,尝试所有构造函数,其中CLS(std::string)可以是因为有std::string(char const *)可用的转换而使用.
详情:
"5"是(C)字符串文字.它的类型是char const [2].首先,搜索用户定义的从该类型的转换CLS.因为没有被发现,从标准转换Type[N]到Type *(有Type= char const和N= 2)被施加,导致char const *.然后编译器尝试从中查找用户定义的转换CLS.因为它找不到一个,并且没有更多的标准转换它可以尝试,编译失败.