C++:在使用委托构造函数时选择 `const char *` 与 `std::string`
C++: choosing a `const char *` vs `std::string` when using delegating constructor
考虑以下几点:
class Foo {
public:
Foo (const char *in) {
printf ("C string constructor called\n");
}
Foo (std::string const &in) : Foo(in.c_str()) {
printf ("C++ string constructor called\n");
}
};
Foo bar ("I never asked for this");
//C string constructor called
因此,常量 string
被视为 const char *
。
但是,如果我们创建一个 std::string
构造函数 "primary",会发生什么变化?
我们是否可以期望创建一个 std::string
对象并将其传递给相应的构造函数而不调用与 C 字符串相关的构造函数?
class Foo {
public:
Foo (std::string const &in) {
printf ("C++ string constructor called\n");
}
Foo (const char *in) : Foo(std::string (in)) {
printf ("C string constructor called\n");
}
};
Foo bar ("I never asked for this");
//C++ string constructor called
//C string constructor called
同样,C 字符串构造函数被调用 first。
这种行为是在 C++ 标准中描述的,还是与编译器相关的?
例如,这是否会以相同的方式工作?模板还是重载函数?
我用 GCC 7.3.0 (MSYS2 x64) 编译。
C++ 中没有 primary 构造函数。
您观察到委托给构造函数(目标构造函数)的主体首先被执行。然后是委托的构造函数的主体(委托构造函数)。
In this case, the target constructor is selected by overload resolution and executed first, then the control returns to the delegating constructor and its body is executed.
"I never asked for this"
是一个 string literal,由 const char
个元素组成:
Foo bar ("I never asked for this"); // calls Foo (const char *in)
因此,Foo (const char *in)
将始终通过重载决议 被选中 ,而不管您在其中 "order" 的 声明你的构造函数。
如第二个示例所示,
Foo (const char *in) : Foo(std::string (in))
delegating constructor 被选中并将调用 目标构造函数,由初始化列表的唯一成员选择。
Overload Resolution and Constructor Delegation是两个完全不同的东西,完全不会互相影响
重载解决方案尽可能避免隐式转换。
像 "I never asked for this"
这样的字符串文字是 const char[]
,它会衰减到 const char *
。这与您的 const char *
构造函数完全匹配,因此它就是被调用的构造函数。使用字符串文字作为输入调用 std::string
构造函数需要隐式转换,因为编译器会构造一个临时 std::string
对象来绑定到 std::string const &
引用。
你是否编写了这段代码:
Foo bar (std::string("I never asked for this"));
或者这个:
std::string str = "I never asked for this";
Foo bar (str);
然后将调用 std::string const &
构造函数而不是 const char *
构造函数,因为没有从 std::string
到 const char *
的隐式转换。
在编译器决定调用哪个构造函数后,构造函数如何相互委托是一个实现细节。
考虑以下几点:
class Foo {
public:
Foo (const char *in) {
printf ("C string constructor called\n");
}
Foo (std::string const &in) : Foo(in.c_str()) {
printf ("C++ string constructor called\n");
}
};
Foo bar ("I never asked for this");
//C string constructor called
因此,常量 string
被视为 const char *
。
但是,如果我们创建一个 std::string
构造函数 "primary",会发生什么变化?
我们是否可以期望创建一个 std::string
对象并将其传递给相应的构造函数而不调用与 C 字符串相关的构造函数?
class Foo {
public:
Foo (std::string const &in) {
printf ("C++ string constructor called\n");
}
Foo (const char *in) : Foo(std::string (in)) {
printf ("C string constructor called\n");
}
};
Foo bar ("I never asked for this");
//C++ string constructor called
//C string constructor called
同样,C 字符串构造函数被调用 first。
这种行为是在 C++ 标准中描述的,还是与编译器相关的?
例如,这是否会以相同的方式工作?模板还是重载函数?
我用 GCC 7.3.0 (MSYS2 x64) 编译。
C++ 中没有 primary 构造函数。
您观察到委托给构造函数(目标构造函数)的主体首先被执行。然后是委托的构造函数的主体(委托构造函数)。
In this case, the target constructor is selected by overload resolution and executed first, then the control returns to the delegating constructor and its body is executed.
"I never asked for this"
是一个 string literal,由 const char
个元素组成:
Foo bar ("I never asked for this"); // calls Foo (const char *in)
因此,Foo (const char *in)
将始终通过重载决议 被选中 ,而不管您在其中 "order" 的 声明你的构造函数。
如第二个示例所示,
Foo (const char *in) : Foo(std::string (in))
delegating constructor 被选中并将调用 目标构造函数,由初始化列表的唯一成员选择。
Overload Resolution and Constructor Delegation是两个完全不同的东西,完全不会互相影响
重载解决方案尽可能避免隐式转换。
像 "I never asked for this"
这样的字符串文字是 const char[]
,它会衰减到 const char *
。这与您的 const char *
构造函数完全匹配,因此它就是被调用的构造函数。使用字符串文字作为输入调用 std::string
构造函数需要隐式转换,因为编译器会构造一个临时 std::string
对象来绑定到 std::string const &
引用。
你是否编写了这段代码:
Foo bar (std::string("I never asked for this"));
或者这个:
std::string str = "I never asked for this";
Foo bar (str);
然后将调用 std::string const &
构造函数而不是 const char *
构造函数,因为没有从 std::string
到 const char *
的隐式转换。
在编译器决定调用哪个构造函数后,构造函数如何相互委托是一个实现细节。