【问题标题】:Returning constructor arguments in function, calls the constructor on return在函数中返回构造函数参数,在返回时调用构造函数
【发布时间】:2013-10-03 13:52:51
【问题描述】:

我遇到了一些令我惊讶的代码。这在 Visual Studio 2012 中编译并且运行良好。

描述类

class Description {
public:
    Description(bool valid = false);
    ~Description(void);
};

主要

Description functionThatReturnsADescription()
{
    return 1;
}

int main()
{
    Description theDescription = functionThatReturnsADescription();
}

我的困惑在于functionThatReturnsADescription() 方法;返回描述以外的任何对象是合法的吗?如果我将它设置为return 1,它会使用valid = true 调用Description 构造函数。如果我将其设置为return falsereturn 0,它会使用valid = false 调用Description 构造函数。

这是否意味着 C++ 编译器总是使用 return 语句的参数调用函数的返回类型构造函数?我以前怎么不知道?!我会发誓这不是合法的 C++。

【问题讨论】:

  • 尝试阅读有关显式关键字的内容
  • @AnatolyS,我很清楚 explicit 关键字。我很惊讶 return 语句在返回时调用了构造函数;我一直认为它只是复制了一个已经构建的对象。

标签: c++ visual-studio constructor return return-type


【解决方案1】:

返回描述以外的任何对象是合法的吗?

您可以返回任何可隐式转换为Description 的类型。在这种情况下,任何数字类型都可以通过标准转换转换为bool,然后通过非显式构造函数转换为Description

如果您愿意,可以通过声明构造函数explicit 来阻止这种转换。养成这种习惯是个好主意,以避免像这样的意外转换。

这是否意味着 C++ 编译器总是使用 return 语句的参数调用函数的返回类型构造函数??

如果类型不匹配,并且有合适的非显式构造函数用于转换,则可以。

我以前怎么不知道?!

C++ 是一门复杂的语言。十五年后,我仍然不断地发现我不知道的东西。

【讨论】:

  • 我真的从来没有想过“可转换类型”可能意味着“可以传递给构造函数以形成另一种类型的有效对象的类型”。说“这个对象是 bool 类型”然后通过说“bool 类型的对象与传递 bool 的描述几乎相同”来转换它是不是有点奇怪?这对我来说似乎是完全错误的行为。我完全希望编译器会抛出错误。我正在尝试找到一些关于此的 C++ 文档,但我找不到它。你知道我在哪里可以找到它吗?
  • @jmbeck:奇怪之处在于您为该类型提供了一个隐式转换构造函数,它明确表示它应该可以从bool 转换。正如我所说,如果该转换没有意义,请将其设为explicit;然后编译器会给出你想要的错误。 (也许有人会争辩说这应该是默认设置;但事实并非如此,所以你只需要学会在适当的时候使用explicit)。如果您需要血淋淋的细节,C++ 12.3 中描述了用户定义的类型转换;他们可以使用非显式转换构造函数或运算符。
  • 我不认为构造函数“用于从输入参数转换”。我将构造函数视为输入参数构建特定类型的函数。将构造函数指定为 explicit 可防止输入参数的转换,例如 float 到 int,或 int 到 boolean。标准转换很有意义,因为它们将类型描述为彼此的子集或超集。我没有看到与对象的构造函数和构造函数输入参数的相同关系。
  • 2012 C++ Specification (pdf) 的第 12.3.1 节让我大吃一惊。我不知道那是合法的 C++。
  • @jmbeck:“我没有看到与对象的构造函数和构造函数输入参数的相同关系。”:对于某些类(比如这个),它没有意义,所以构造函数应该是明确的。对于其他人,确实如此:考虑complex z = 1.0;。构造函数是唯一可以从内置类型转换的可用构造,所以这就是我们使用的。
【解决方案2】:

1 被隐式转换为true,因此选择接受bool 的构造函数。

为了防止这种隐式转换,可以将构造函数标记为explicit,这种情况下只有

return Description(1);

会起作用的。

【讨论】:

    【解决方案3】:

    返回值1 被隐式转换为布尔值true,然后作为参数传递给构造函数。使用构造函数 Description(bool valid = false); 隐式创建 Description 对象。

    需要注意的是,这里发生了两个隐式转换:1 → true → 描述。您可以通过使构造函数explicit 来防止第二次转换。将构造函数的声明改为

    explicit Description(bool valid = false);
    

    但是,第一次转换仍然会发生,即仍然可以进行return Description(1);

    参考:What does the explicit keyword in C++ mean?

    【讨论】:

      猜你喜欢
      • 2014-07-25
      • 2021-01-08
      • 2012-08-07
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2019-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多