用字符串文字构造一个对象

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";

ac初始化为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 constN = 2)被应用,导致 char const *。然后编译器试图找到一个用户定义的从那个到 CLS 的转换。因为它没有找到,并且没有更多的标准转换可以尝试,所以编译失败。

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

CLS c("4");direct initializationCLS 的构造函数将被检查以初始化 cCLS::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::stringstd::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)