c++ - auto的推导使编译器生成默认构造函数

标签 c++

考虑这段代码,其编写的唯一目的是练习:

class Param {
 private:
  struct Foo{  
    int bar;
  };
  
public:
  Foo foo;
};

int main()
{
  Param p;
  p.foo.bar = 5;
}

使用 cppInsight 生成此中间代码:

#include <cstdio>

class Param
{
  
  private: 
  struct Foo
  {
    int bar;
    // inline Foo() noexcept = default;
  };
  
  
  public: 
  Foo foo;
  // inline Param() noexcept = default;
};



int main()
{
  Param p = Param();
  p.foo.bar = 5;
  return 0;
}

一切看起来都很好,Param 可以实例化,bar 可以修改,但 Param::Foo 无法实例化。添加一个

int main()
{
  Param p;
  p.foo.bar = 5;
  Param::Foo f = p.foo; // compile error
}

如预期的那样导致编译器错误。但是如果我尝试扣除自动

int main()
{
  Param p;
  p.foo.bar = 5;
  auto f = p.foo; // it works!
}

它确实有效!

使用 cppInsight 检查新的生成代码,如下所示 this :

#include <cstdio>

class Param
{
  
  private: 
  struct Foo
  {
    int bar;
    // inline Foo() noexcept = default;
    // inline constexpr Foo(const Foo &) noexcept = default;
  };
  
  
  public: 
  Foo foo;
  // inline Param() noexcept = default;
};

int main()
{
  Param p = Param();
  p.foo.bar = 5;
  Param::Foo f = Param::Foo(p.foo);
  return 0;
}

使用 auto 的推导使编译器生成默认的复制构造函数并实际实例化。

有人可以解释为什么会发生这种行为吗?

最佳答案

Param::Foo 设为私有(private)意味着您无法通过此名称访问它。 C++ 标准在第 11.9 章(“成员访问控制”)中表示 [ C++20 draft N4860 PDF ]:

A member of a class can be

— private; that is, its name can be used only by members and friends of the class in which it is declared.

[Note: Access to members and base classes is controlled, not their visibility (6.4.10). Names of members are still visible, and implicit conversions to base classes are still considered, when those members and base classes are inaccessible. — end note]

(强调我的)

auto 不使用该名称。

这有时是故意的,例如用于容器的迭代器。这样您就可以仅将迭代器与 auto 一起使用。优点是容器的实现可以在稍后的时间点更改迭代器,而不会破坏您的代码(因为您需要切换到新名称)。

关于c++ - auto的推导使编译器生成默认构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75619237/

相关文章:

c++ - 如何使用数组的 boost 来计算凸包,而不是单独设置每个点?

c++ - 编译错误c++(需要替换),线程有问题吗?

c++ - 未知的 nvlink 错误

c++ - OpenGL 减慢 5k 点

c++ - 在使用 libjpeg 读取 JPEG 文件时需要帮助

c++ - 在编码程序中使用自己的堆栈类 - 确定大小和顶部

c++ - 尝试了解编写 Python/C++ 混合程序的链接过程

java - 如何使用 "DFLT-X"方法编写 Zip 文件

c++ - Linux : Will stat access Hard Disk for its operation

c++ - 本地类型作为未实例化函数内的模板参数