【问题标题】:Default values when returning a class via initializer list (vs2015 vs vs2017)通过初始化列表返回类时的默认值(vs2015 vs vs2017)
【发布时间】:2018-10-15 09:57:01
【问题描述】:

我正在寻找对以下观察结果的解释。 从 vs2017 开始,有问题的代码简写为:

#include <iostream>

class Range
{
public:
  double min = 0; // some default values here
  double max = 1;

  double getRange() const {return max-min;};
};

Range makeRange(double a, double b)
{
  return {a,b}; // the initializer list return in question
}

int main()
{
  const auto x = makeRange(4.0,5.0); // some example application
  std::cout << x.min << ", " << x.max << std::endl;
}

在此,Range 类为“min”和“max”提供默认值,并且可以通过“makeRange”中的初始化程序列表进行初始化。此代码在 VS2017 中编译并运行。

在 VS2015 中,它无法编译(错误 C2440:'return': cannot convert from 'initializer list' to 'Range')。但是,如果删除默认值使得

class Range
{
public:
  double min;
  double max;

  double getRange() const {return max-min;};
};

它在 vs2015 中编译和工作。它仍然会在 VS2017 中编译。但是,默认值是未定义的(我猜)。一旦添加了构造函数,就有了默认值

  Range():min(0),max(0){};

VS2017 编译失败。 所以有两个问题:

  1. 我假设 VS2015 支持初始化列表。为什么第一个代码在 VS2015 中无法编译?为什么在删除默认值时会出现这种情况?
  2. 为什么默认构造函数的定义会破坏VS2017中的初始化列表功能?在成员本身设置默认值显然有效。

【问题讨论】:

    标签: class c++11 return initializer-list


    【解决方案1】:

    您正在使用aggregate initialization。这当然需要 Range 是一个聚合类型。不同版本的标准对聚合的定义进行了很多调整。

    因此,在 C++11 中,具有默认成员初始值设定项的类不能是聚合,但从 C++14 开始可以。看来VS2015使用的是前一种定义,VS2017使用的是后者。

    具有用户提供的构造函数的类在任何版本的标准中都不是聚合。

    【讨论】:

    • 非常感谢您澄清这一点!解释很有帮助!
    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 2019-09-10
    • 1970-01-01
    • 2014-05-06
    • 2017-11-19
    • 1970-01-01
    • 2014-12-29
    • 2012-01-16
    相关资源
    最近更新 更多