【问题标题】:Automatic Object Construction in Function Parameters by Passing Constructor Parameters通过传递构造函数参数在函数参数中自动构造对象
【发布时间】:2020-03-22 17:33:35
【问题描述】:

你能解释一下为什么下面的代码会编译和运行吗?这里的概念是什么,这种方法的工作限制/要求是什么?

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

我希望这段代码无法编译。 foo() 将一个字符串参数传递给 bar(),而 bar 只接受一个 string_wrapper 参数。但是,编译器足够聪明,知道它可以将字符串参数用作 string_parameter 对象的构造函数的参数,然后大概将其作为实际参数传递给 bar()。

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

【问题讨论】:

标签: c++ constructor parameter-passing


【解决方案1】:

这里发生的是隐式构造。你说得对,编译器足够“聪明”,知道你可以从std::string 创建一个string_wrapper,它也会自动为你创建。

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-16
    • 2017-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-09
    • 2011-09-05
    相关资源
    最近更新 更多