C++ 文件*、fopen_s和初始化列表

C++ 文件*、fopen_s和初始化列表,c++,initialization-list,C++,Initialization List,我有一个这样声明的类(仅显示相关部分): 构造函数将打开一个文件: X::X(int x) : _x(x) { int err = fopen_s(&stream, "myfile.txt", "w"); fputs("some text", stream); ... } 它用于另一个类,如: class Y { public: Y(); private: X myX; } 在Y的构造函数中,通过初始化列表初始化myX,并在其上

我有一个这样声明的类(仅显示相关部分):

构造函数将打开一个文件:

X::X(int x) : _x(x)
{
   int err = fopen_s(&stream, "myfile.txt", "w");
   fputs("some text", stream);
   ...
}
它用于另一个类,如:

class Y
{
   public:
      Y();

   private:
      X myX;
}
在Y的构造函数中,通过初始化列表初始化myX,并在其上调用一个方法:

Y::Y() : myX(100)
{
   myX.init();
}

当我逐步遍历X的构造函数时,流被分配并写入,没有错误。如果我在Y的构造函数的左大括号处放置断点,则stream的值与X的构造函数中的值相同。但是,当我进入Y的构造函数体时,stream的值会发生变化,并且下次使用它(例如在init()中)会导致访问冲突。如果我将Y更改为存储指向X的指针,而不是直接引用,并在堆上分配X,则一切正常。我怀疑这与fopen_s分配文件*的位置有关,但我无法证实这一点。有人能解释为什么失败吗?

你也应该显示init(),考虑不要在你的构造函数中做工作,然后添加一个init给y,然后调用它的x()上的init。如果你做了一个干净的重建?侧栏,这个错误仍然存在:标识符(变量名、类型、宏定义等等)。前导下划线由编译所依据的实现保留。也就是说,
\ux
是一个坏习惯,你现在应该在学习的过程中改掉它
x_u
x
,等等都很好。另外,如果需要在构造函数中执行此操作,请声明x private的默认构造函数,这样您就不会意外地在其中创建一个包含无效文件*的x。
Y::Y() : myX(100)
{
   myX.init();
}