构造函数中的 const 参数会导致 stackoverflow

发布于 2024-09-03 13:39:09 字数 536 浏览 5 评论 0原文

我在 VS2005 C++ 编译器中发现了这种奇怪的行为。情况是这样的:

我无法发布代码,但情况很简单。

这是初始代码:它工作完美

class Foo {
     public:
     Foo(Bar &bar) { ... }
}

构造函数实现存储引用,设置一些成员......确实没有什么特别的。

如果我按以下方式更改代码:

class Foo {
     public:
     Foo(const Bar &bar) { ... }
}

我已将 const 限定符添加到唯一的构造函数例程参数中。

它编译正确,但编译器输出一条警告,指出例程 Foo::Foo 将导致堆栈溢出(即使执行路径不构造任何对象 Foo);实际上,这种情况发生了。

那么,为什么没有 const 参数的代码可以完美运行,而带有 const 限定符的代码却会导致堆栈溢出呢?什么会导致这种奇怪的行为?

I've found this strange behavior with VS2005 C++ compiler. Here is the situation:

I cannot publish the code, but situation is very simple.

Here is initial code: it work perfectly

class Foo {
     public:
     Foo(Bar &bar) { ... }
}

The constructor implementation stores a reference, setup some members... indeed nothing special.

If I change the code in the following way:

class Foo {
     public:
     Foo(const Bar &bar) { ... }
}

I've added a const qualifier to the only constructor routine parameter.

It compiles correctly, but the compiler outputs a warning saying that the routine Foo::Foo will cause a stackoverflow (even if the execution path doesn't construct any object Foo); effectively this happens.

So, why the code without the const parameter works perfectly, while the one with the const qualifier causes a stackoverflow? What can cause this strange behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陪我终i 2024-09-10 13:39:09

尝试使用 explicit 关键字?

我的猜测是,使用 const,您声明了从 Bar 到 Foo 的自动转换;如果您已经有任何类似的从 Foo 到 Bar 的自动转换,那么会溢出吗?

Try usng the explicit keyword?

My guess is that, with const, you're declaring an automatic conversion from Bar to Foo; and if you already have any similarly automatic conversion from Foo to Bar, then overflow?

饮惑 2024-09-10 13:39:09

导致堆栈溢出的唯一方法(除了编译器中的错误,在我从事 C++ 的 15 年中,我发现与我自己的错误相比很少见)是 Foo(const Bar& ;) 创建一个 Foo 对象,并向其传递一个 Bar 对象。此类错误可能很微妙,很难通过查看代码来发现。

但如果您有 VS2005,那么您手头上就有一个非常好的调试器。在该构造函数中放置一个断点,运行程序直到遇到断点,然后再次运行,直到第二次遇到断点。检查堆栈将向您展示它是如何发生的。

如果不是每次调用该构造函数都会导致堆栈溢出,则可以添加以下代码:

namespace { unsigned int recursion_detector = 0; }

Foo::foo(const Bar& bar)
{
  if(recursion_detector++)
    ++recursion_detector; // meaningless code just to put a breakpoint here
  // rest of constructor code
}

并在指示的行上放置一个断点,当递归发生时将命中该断点。

The only way for this to cause a stack overflow (besides a bug in the compiler, which, in my 15 years of doing C++, I have found rare compared to my own errors) is that Foo(const Bar&) creates a Foo object passing it a Bar object. Bugs like these can be subtle and hard to find by looking at the code.

But if you have VS2005, you have a pretty good debugger at hand. Put a breakpoint into that constructor, run the program until you hit the breakpoint, then run again until you hit the breakpoint the second time. Examination of the stack will show you how it happens.

If not every call to this constructor will cause a stack overflow, you can add this code:

namespace { unsigned int recursion_detector = 0; }

Foo::foo(const Bar& bar)
{
  if(recursion_detector++)
    ++recursion_detector; // meaningless code just to put a breakpoint here
  // rest of constructor code
}

and put a breakpoint on the line indicated, which will be hit when the recursion occurs.

盛装女皇 2024-09-10 13:39:09

您可以将参数从 const Bar &bar 更改为 const Bar *bar。
它会工作得很好,您只需要更改管理参数栏的方式(从引用到指针)。

对象初始化会是这样的:

Bar mybar;

...

Foo myfoo(&mybar);


class Foo {
     public:
     Foo(const Bar *bar) { ... }
};

这并没有那么糟糕......

You could change the parameter from const Bar &bar to const Bar *bar.
It will work fine, you would just have to change the way you manage the parameter bar (from a referente to a pointer).

The object initialization would be something like:

Bar mybar;

...

Foo myfoo(&mybar);


class Foo {
     public:
     Foo(const Bar *bar) { ... }
};

It's not that bad...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文