voi*_*ter 3 c++ initialization copy-initialization
我有以下代码:
#include <string_view>
class Foo
{
public:
Foo(std::string_view) {}
};
Run Code Online (Sandbox Code Playgroud)
当我这样做时,一切都可以正常编译(使用clang v8,C ++ 17):
Foo f("testing");
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用副本初始化,它将失败:
Foo f = "testing";
Run Code Online (Sandbox Code Playgroud)
诊断:
prog.cc:15:9: error: no viable conversion from 'const char [8]' to 'Foo'
Foo f = "testing";
^ ~~~~~~~~~
prog.cc:7:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char [8]' to 'const Foo &' for 1st argument
class Foo
^
prog.cc:7:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'const char [8]' to 'Foo &&' for 1st argument
class Foo
^
prog.cc:10:5: note: candidate constructor not viable: no known conversion from 'const char [8]' to 'std::string_view' (aka 'basic_string_view<char>') for 1st argument
Foo(std::string_view) {}
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
查看string_view的构造函数,我看不到有任何重载,char const[]这可能是问题吗?我意识到我可以用它"testing"sv来解决这个问题,但是我觉得字符串文字大小写也应该起作用。
为什么复制初始化案例不起作用?如何使其与字符串文字一起使用?
Foo f = "testing";是复制初始化,要求从"testing"(类型const char[8])隐式转换为Foo。"testing"可能衰减到const char*,然后仍然需要两个用户定义的转换。从const char*到的转换std::string_view,以及从std::string_view到的转换Foo。但是在一个隐式转换序列中仅允许一次用户定义的转换。
Foo f("testing");是直接初始化,其行为有所不同。"testing"衰减为const char*,然后转换为std::string_view,用作Foo的构造函数的参数f直接进行初始化。
另外,复制初始化中的隐式转换必须直接从初始值设定项产生T,而直接初始化期望从初始值设定项到T的构造函数的参数的隐式转换。
隐式转换是根据复制初始化定义的:如果可以使用表达式E复制类型T的对象,则E可以隐式转换为T。
解决方法是,如果要坚持复制初始化,可以减少所需的用户定义转换。如您所展示的,应用Foo f = "testing"sv;或Foo f = std::string_view("testing");具有一个相同的效果是一个好主意。