通过传递构造函数参数的自动参数构造

问题描述 投票:0回答:1

您能否解释为什么以下代码会编译并运行?这里的概念是什么?使用这种方法的局限性/要求是什么?

class string_wrapper
{
public:
    string_wrapper(string i_string);

    string m_value;
    int m_length;
};

string_wrapper::string_wrapper(string i_string)
{
    m_value = i_string;
    m_length = i_string.length();
}

void bar(string_wrapper i_param)
{
    cout << i_param.m_value << std::endl;
}

void foo()
{
    string test_string = "test1";

    bar(test_string);
}

int main()
{
    test_function_b();
}

输出:

test1

我希望此代码无法编译。当bar仅采用string_wrapper参数时,foo()将字符串参数传递给bar()。但是,编译器很聪明,知道它可以将string参数用作string_parameter对象的构造函数的参数,然后大概将其作为实际参数传递给bar()。

这是C ++标准中的行为,还是我的编译器所独有的(在这种情况下,Visual Studio 2017版本15.9)?我可以用于进一步研究的任何见解或术语将不胜感激。

c++ constructor parameter-passing
1个回答
0
投票

这里发生的是隐式构造。您正确地知道编译器“很聪明”,足以知道您可以从string_wrapper中创建一个std::string,因此自动为您创建。

要停止这种情况,您可以像这样使用explcit关键字:

...
explicit string_wrapper(string i_string);
...

explicit关键字告诉编译器您不希望它为string_wrapper之外的对象自动构造std::string对象。由于可以防止意外构造对象(尤其是在函数返回和传递参数时),因此可以阻止错误跟踪。

当对象只有一个非默认参数时可能会发生隐式构造(隐式转换也是您应该研究的东西)。它可以是功能强大的工具,并且可以允许代理类和透明API(即std::vector的参考类)之类的东西。通常,除非不做设计决定,否则应声明单个参数(或单个非默认值)的构造函数(和转换运算符)explicit

© www.soinside.com 2019 - 2024. All rights reserved.