用字符串文字构造一个对象
Construct an object with a string literal
我有以下 class:
#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'
}
我搜索了错误的原因,没有运气。
用字符串文字构造是否正确?
如果没有,为什么?
如果是,我的代码有什么问题?
我在 Code::Blocks 16.1.
中使用 gcc 5.3
CLS a(2);
CLS b = 3;
CLS c("4");
CLS d = "5";
a
和c
初始化为direct initialisation. b
and d
on the other hand use copy initialisation。
不同之处在于,对于复制初始化,编译器搜索(单个)用户定义的转换(在 d
的情况下)char const *
(这有点不准确,请参阅答案结尾) 到 CLS
,而对于直接初始化,将尝试所有构造函数,其中可以使用 CLS(std::string)
,因为有可用的转换 std::string(char const *)
。
详情:
"5"
是 (C) 字符串文字。它的类型是char const [2]
。因此,首先,搜索从该类型到 CLS
的用户定义转换。因为找到 none,所以从 Type[N]
到 Type *
的标准转换(使用 Type
= char const
和 N
= 2
)被应用,导致 char const *
。然后编译器试图找到一个用户定义的从那个到 CLS
的转换。因为它没有找到,并且没有更多的标准转换可以尝试,所以编译失败。
起初,"4"
不是 std::string
,而是 const char[2]
。然后
CLS c("4");
是 direct initialization,CLS
的构造函数将被检查以初始化 c
。 CLS::CLS(string)
在这里被拾取,因为 const char[]
可以通过用户定义的转换隐式转换为 std::string
(即通过 std::string::string(const char*)
)。
CLS d = "5";
是 copy initialization,
(强调我的)
- If
T
is a class type, and the cv-unqualified version of the type of other
is not T
or derived from T
, or if T
is non-class type, but the type of other
is a class type, user-defined conversion sequences that can convert from the type of other
to T
(or to a type derived from T
if T
is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.
这意味着需要用户定义的转换序列才能将const char[2]
转换为CLS
。即使const char[]
也可以转成std::string
,std::string
也可以转成CLS
,但一个implicit conversion sequence中只能有一个用户自定义转换。这就是它被拒绝的原因。
(强调我的)
Implicit conversion sequence consists of the following, in this order:
1) zero or one standard conversion sequence;
2) zero or one user-defined conversion;
3) zero or one standard conversion sequence.
顺便说一句:如果您将其显式更改为使用 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)
我有以下 class:
#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'
}
我搜索了错误的原因,没有运气。
用字符串文字构造是否正确? 如果没有,为什么? 如果是,我的代码有什么问题?
我在 Code::Blocks 16.1.
中使用 gcc 5.3CLS a(2);
CLS b = 3;
CLS c("4");
CLS d = "5";
a
和c
初始化为direct initialisation. b
and d
on the other hand use copy initialisation。
不同之处在于,对于复制初始化,编译器搜索(单个)用户定义的转换(在 d
的情况下)char const *
(这有点不准确,请参阅答案结尾) 到 CLS
,而对于直接初始化,将尝试所有构造函数,其中可以使用 CLS(std::string)
,因为有可用的转换 std::string(char const *)
。
详情:
"5"
是 (C) 字符串文字。它的类型是char const [2]
。因此,首先,搜索从该类型到 CLS
的用户定义转换。因为找到 none,所以从 Type[N]
到 Type *
的标准转换(使用 Type
= char const
和 N
= 2
)被应用,导致 char const *
。然后编译器试图找到一个用户定义的从那个到 CLS
的转换。因为它没有找到,并且没有更多的标准转换可以尝试,所以编译失败。
起初,"4"
不是 std::string
,而是 const char[2]
。然后
CLS c("4");
是 direct initialization,CLS
的构造函数将被检查以初始化 c
。 CLS::CLS(string)
在这里被拾取,因为 const char[]
可以通过用户定义的转换隐式转换为 std::string
(即通过 std::string::string(const char*)
)。
CLS d = "5";
是 copy initialization,
(强调我的)
- If
T
is a class type, and the cv-unqualified version of the type ofother
is notT
or derived fromT
, or ifT
is non-class type, but the type ofother
is a class type, user-defined conversion sequences that can convert from the type ofother
toT
(or to a type derived fromT
ifT
is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.
这意味着需要用户定义的转换序列才能将const char[2]
转换为CLS
。即使const char[]
也可以转成std::string
,std::string
也可以转成CLS
,但一个implicit conversion sequence中只能有一个用户自定义转换。这就是它被拒绝的原因。
(强调我的)
Implicit conversion sequence consists of the following, in this order:
1) zero or one standard conversion sequence;
2) zero or one user-defined conversion;
3) zero or one standard conversion sequence.
顺便说一句:如果您将其显式更改为使用 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)