调用带字符串参数的构造函数传递char * 报错

Calling constructor with string argument passing char * report error

template<typename T>
class SharedValue {
public:
    SharedValue(const T& t): valuePtr(new T(t)) {}
    
    const SharedValue& operator = (const T &t) {
        *valuePtr = t;
        return *this;
    }
  
protected:
    dd_shared_ptr<T> valuePtr;
};

typedef SharedValue<std::string> SharedString;
 
int main(int argc, const char * argv[]) {
    // compile succeeded
    SharedString str(argv[0]);

    // compile failed:
    SharedString str2 = argv[0];
   
    return 0;
}

str2构建失败,报告:

No viable conversion from 'const char *' to 'SharedString' (aka 'SharedValue<basic_string<char, char_traits<char>, allocator<char>>>')

为什么str成功而str2失败,有什么区别吗?

Why str succeeded whereas str2 failed, is there any difference?

是的,两者是有区别的。特别是,在 str 中我们有 直接初始化 而在 str2 中我们有 复制初始化.

您的程序的行为可以从 copy initialization documentation 中理解,其中指出:

In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.

(强调我的)

现在让我们根据具体情况将其应用于您给出的示例。

案例一

这里我们考虑语句:

SharedString str2 = argv[0]; //this is copy initialization

以上使用复制初始化。由于 SharedString 不能直接从右侧 const char* 类型的 初始化器 生成,因为它需要隐式转换,所以这种情况 1 不是'根据上述引用声明,t 允许。

案例二

这里我们考虑语句:

SharedString str(argv[0]); //this is direct initialization

虽然上面使用了直接初始化并且因为有一个隐式转换可用(使用转换构造函数), 这次按照上面引用的说法是允许的