C++ 构造函数之后立即调用析构函数

C++ 构造函数之后立即调用析构函数,c++,c++11,constructor,destructor,C++,C++11,Constructor,Destructor,我试图创建一个Window类,但由于某种原因,一个Window对象的简单定义之后会立即调用它的析构函数 窗口类的标头定义了以下构造函数和复制控件:- Window(); Window(int); Window(const char* title); Window(string title); Window(const char* title, int x, int y, int width, int height); Window(string title, int x, int y, int

我试图创建一个Window类,但由于某种原因,一个Window对象的简单定义之后会立即调用它的析构函数

窗口类的标头定义了以下构造函数和复制控件:-

Window();
Window(int);
Window(const char* title);
Window(string title);
Window(const char* title, int x, int y, int width, int height);
Window(string title, int x, int y, int width, int height);
Window(const Window &window);
Window& operator=(const Window &window);
~Window();
这些功能的相关代码如下所示:-

Window::Window()
{
  Window(default_title, default_width, default_height, default_xpos, default_ypos);
}

Window::Window(int)
:title_(default_title),
size_({ default_width, default_height }),
position_({ default_xpos, default_ypos })
{
  context_ = glutCreateWindow(title_.c_str());
  setposition(position_);
  setsize(size_);
  glutSetWindow(context_);
}

Window::Window(string title)
:Window(title, default_width, default_height, default_xpos, default_ypos)
{ }

Window::Window(const char* title)
{
  string t(title);
  Window(t, default_width, default_height, default_xpos, default_ypos);
}


Window::Window(const char* title, int x, int y, int width, int height)
{
  string t(title);
  Window(t, width, height, x, y);
}

Window::Window(string title, int x, int y, int width, int height)
:title_(title),
size_({ width, height }),
position_({ x, y })
{
  context_ = glutCreateWindow(title.c_str());
  refresh();
  setcallbacks();
  glutSetWindow(context_);
}

Window::Window(const Window &window)
:title_(window.title_),
size_(window.size_),
position_(window.position_)
{
  context_ = glutCreateWindow(title_.c_str());
  refresh();
  glutSetWindow(context_);
}

Window& Window::operator= (const Window &window)
{
  title_ = window.title_;
  size_ = window.size_;
  position_ = window.position_;
  context_ = window.context_;
  refresh();
  glutSetWindow(context_);
  return *this;
}

Window::~Window()
{
  glutDestroyWindow(context_);
}
上面代码中使用的其他函数,如refresh()和setcallbacks()都没有直接调用该类,而是调用glut函数。如果你认为它们相关,我会把它们包括在内

问题行如下所示,作为主函数的一部分调用:-

Window win("blah");

我尝试过几种配置,包括空构造函数、完整构造函数和赋值,但似乎都不起作用。据我所知,构造函数按预期运行并初始化所有变量,然后在进入主函数中的下一个语句时莫名其妙地调用析构函数。

这是因为不能这样调用构造函数:

Window::Window(const char* title, int x, int y, int width, int height)
{
  string t(title);
  Window(t, width, height, x, y); // this create a temporary Window then destroy it
}
而是这样做:

Window::Window(const char* title, int x, int y, int width, int height)
    : Window( string(t), width, height, x, y)
{}

这是因为您不能像这样调用构造函数:

Window::Window(const char* title, int x, int y, int width, int height)
{
  string t(title);
  Window(t, width, height, x, y); // this create a temporary Window then destroy it
}
而是这样做:

Window::Window(const char* title, int x, int y, int width, int height)
    : Window( string(t), width, height, x, y)
{}

要理解为什么代码不能按您希望的方式工作,您需要知道构造函数调用是如何工作的

例如,在默认构造函数中,调用另一个将创建窗口对象的构造函数。但是这个新对象被限制在默认构造函数范围内!因此,当您离开此作用域时(当默认构造函数调用结束时),对象将通过调用其析构函数来销毁

您可以观察到这一点,因为在下面的构造函数中,您创建了一个glut窗口(
context\uuu
),并对其进行了设置:

Window(string title, int x, int y, int width, int height)
然后,在析构函数中,销毁这个glut窗口。请注意,您只调用了临时对象的析构函数,该对象限制在默认构造函数范围内!对默认构造函数的原始调用仍然会创建一个保持在另一个作用域中的
窗口(空窗口)

要解决这个问题并做您最初想要做的事情,您需要使用(仅限C++11)。您可以通过调用构造函数初始化列表中的另一个构造函数来完成此操作,如下所示:

Window::Window(/* some arguments */)
    : Window(/* other arguments (other constructor) */) {
    // other stuff
}
还请注意,您可以使用默认参数。例如:

Window(string title = default_title,
       int x = default_xpos, int y = default_ypos,
       int width = default_width, int height = default_height);

我认为您在调用中用维度交换了坐标。

要理解代码为什么不能按您希望的方式工作,您需要知道构造函数调用是如何工作的

例如,在默认构造函数中,调用另一个将创建窗口对象的构造函数。但是这个新对象被限制在默认构造函数范围内!因此,当您离开此作用域时(当默认构造函数调用结束时),对象将通过调用其析构函数来销毁

您可以观察到这一点,因为在下面的构造函数中,您创建了一个glut窗口(
context\uuu
),并对其进行了设置:

Window(string title, int x, int y, int width, int height)
然后,在析构函数中,销毁这个glut窗口。请注意,您只调用了临时对象的析构函数,该对象限制在默认构造函数范围内!对默认构造函数的原始调用仍然会创建一个保持在另一个作用域中的
窗口(空窗口)

要解决这个问题并做您最初想要做的事情,您需要使用(仅限C++11)。您可以通过调用构造函数初始化列表中的另一个构造函数来完成此操作,如下所示:

Window::Window(/* some arguments */)
    : Window(/* other arguments (other constructor) */) {
    // other stuff
}
还请注意,您可以使用默认参数。例如:

Window(string title = default_title,
       int x = default_xpos, int y = default_ypos,
       int width = default_width, int height = default_height);

我认为您在调用中用维度交换了坐标。

如果您调用了
windowwin(“废话”)不在实际作用域中使用它,下一步是按预期调用析构函数如果不在实际作用域中使用它,下一步是按预期调用析构函数。但是应该注意的是,这只能从C++11开始实现。是的,但我先检查了,问题被标记为C++11,所以…这似乎起到了作用,谢谢。只是想澄清一下,从另一个构造函数中调用窗口构造函数是否存在问题?编辑:错过了评论,是的。我同意@MatteoItalia委托构造函数从C++11及以后都受支持。你也应该给出带有初始值设定项列表的经典解决方案作为备选方案。@galop1n:当然,事实上我还是对你的答案投了赞成票。这仅仅是为了完整性和对未来访客的清晰性。:)但是需要注意的是,这只在C++11以后才可能实现。是的,但我先检查了,问题被标记为C++11,所以…这似乎有效,谢谢。只是想澄清一下,从另一个构造函数中调用窗口构造函数是否存在问题?编辑:错过了评论,是的。我同意@MatteoItalia委托构造函数从C++11及以后都受支持。你也应该给出带有初始值设定项列表的经典解决方案作为备选方案。@galop1n:当然,事实上我还是对你的答案投了赞成票。这仅仅是为了完整性和对未来访客的清晰性。:)