为什么 const char* 隐式转换为 bool 而不是 std::string?

Why const char* implicitly converted to bool rather than std::string?

#include <iostream>
#include <string>

struct mystruct{
     mystruct(std::string s){
        
        std::cout<<__FUNCTION__ <<" String "<<s;
    }
    
     explicit mystruct(bool s) {
        
        std::cout<<__FUNCTION__<<" Bool "<<s;
    }
};


int main()
{
    
    const char* c ="hello";
    
    mystruct obj(c);

    return 0;
}

输出:

mystruct Bool 1
  1. 为什么 const char* 隐式转换为 bool 而不是 std::string,尽管构造函数需要 explicit 类型?
  2. 这里如何应用隐式转换优先级?

因为const char*bool的隐式转换是标准转换,而const char*std::string是用户自定义转换。前者排名较高,在overload resolution.

中获胜

A standard conversion sequence is always better than a user-defined conversion sequence or an ellipsis conversion sequence.

顺便说一句:mystruct obj(c); 执行 direct initializationexplicit 也考虑转换构造函数,包括 mystruct::mystruct(bool)。结果,c 被转换为 bool,然后传递给 mystruct::mystruct(bool) 作为构造 obj.

的参数

Direct-initialization is more permissive than copy-initialization: copy-initialization only considers non-explicit constructors and non-explicit user-defined conversion functions, while direct-initialization considers all constructors and all user-defined conversion functions.

关于 explicit specifier,

  1. Specifies that a constructor or conversion function (since C++11) or deduction guide (since C++17) is explicit, that is, it cannot be used for implicit conversions and copy-initialization.

“尽管构造函数需要 explicit 类型,但为什么 const char* 隐式转换为 bool 而不是 std::string?”:

  • 标准转换优先于用户定义的转换。

char const* 是指向常量字符的指针,指针可以隐式转换为 bool :如果它是 nullptr,则转换为 false 否则为true.

  • 您曾经在检查指针是否为 NULL 的情况下看到过这种有效的转换,因此如果它不是 nulptr 我们可以安全地取消引用它否则它具有 nullptr 值,因此取消引用它是不正确的:

    int* ptr = nullptr;
    
    if(ptr) // false  because ptr has nullptr or NULL or 0 or 0x000000 address value
       std::cout << ptr << '\t' << *ptr << '\n'; // not executed
    
    ptr = new int(10); // valid and non-nullptr
    
    if(ptr) // non-nullptr so condition succeeds
       std::cout << ptr << '\t' << *ptr << '\n'; // 0FED155   10
     delete ptr; // free memory
    
  • explicit 构造函数意味着它只能被显式调用,唯一的方法是像你的情况一样通过直接初始化:

    mystruct obj(c); // direct initialization
    mystruct obj = c; // copy-initialization. Error: constructor myStruct(bool) is `explicit`