1

考虑以下:

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构造函数设为“主要”,会发生什么变化?

我们可以期望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 字符串构造函数。

这种行为是在 C++ 标准中描述的,还是与编译器相关的?

这对于例如模板或重载函数的工作方式是否相同?

我用 GCC 7.3.0 (MSYS2 x64) 编译。

4

3 回答 3

3

"I never asked for this"是一个字符串文字,由以下const char元素组成:

Foo bar ("I never asked for this"); // calls Foo (const char *in)

因此,无论您声明构造函数的“顺序”如何,Foo (const char *in)都将始终被重载决议选中。

如您的第二个示例所示,

Foo (const char *in) : Foo(std::string (in))

委托构造函数被选中并将调用目标构造函数,由初始化列表的唯一成员选择。

于 2018-06-20T15:04:29.340 回答
2

C++中没有构造函数之类的东西。

您观察到的是委托给构造函数(目标构造函数)的主体首先执行。然后是委托的构造函数的主体(委托构造函数)。

委托构造函数

在这种情况下,通过重载决议选择目标构造函数并首先执行,然后控制返回到委托构造函数并执行其主体。

于 2018-06-20T14:59:52.263 回答
1

重载解析构造函数委托是两个完全不同的东西,它们根本不会相互影响。

重载解决方案尽可能避免隐式转换。

"I never asked for this"像a这样的字符串文字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::stringto的隐式转换const char *

构造函数如何相互委托是编译器决定调用哪个构造函数之后的实现细节。

于 2018-06-20T17:13:20.653 回答