为啥 `throw MyClass' 不起作用而 `throw MyClass()' 起作用?

Posted

技术标签:

【中文标题】为啥 `throw MyClass\' 不起作用而 `throw MyClass()\' 起作用?【英文标题】:Why `throw MyClass' doesn't work and `throw MyClass()' does?为什么 `throw MyClass' 不起作用而 `throw MyClass()' 起作用? 【发布时间】:2012-09-27 11:48:48 【问题描述】:

我在某处读到(现在找不到源)

MyClass *p1 = new MyClass;

MyClass *p2 = new MyClass();

本质上是等价的,前提是MyClass 提供了一个默认构造函数。编译器了解我想要做什么并添加空括号。

如果是这样,为什么不让我写

throw MyException;

但必须使用

throw MyException();

? (是的,行首的问号。)

为了增加一些混乱,C++ FAQ 建议第二个用例 (new MyClass()) 不调用构造函数,而是调用用 operator() 定义的函数。

【问题讨论】:

C++ 中一个有趣的怪癖:不能有值初始化的自动对象,也不能有默认初始化的临时对象。 【参考方案1】:

编译器理解我想要做什么并添加空括号。

不,它没有;这两个表达式并不完全等价。不同之处在于对象的初始化方式:第一个使用默认初始化,而第二个使用值初始化。所以它们对于定义默认构造函数的类是等价的;否则,第一个将保留 POD 对象未初始化,而第二个会将它们初始化为零。

为什么我不能写throw MyException;

MyException() 是一个创建值初始化临时对象的表达式;你可以抛出它,就像你可以抛出任何其他合适的表达式的值一样。

MyException 不是表达式;它只是一个类型名称。你只能抛出一个表达式的值,所以throw MyException; 是无效的。无法创建默认初始化的临时对象。

为了增加一些混乱,C++ FAQ 建议第二个用例 (new MyClass()) 不调用构造函数,而是调用使用 operator() 定义的函数。

不,它没有。它说像List x(); 这样的声明声明了一个返回类型为List 的函数,而不是(正如人们可能认为的)类型为List 的值初始化对象。它与 new-expressions 或 operator() 无关。

【讨论】:

为了确保我理解正确:“第一个使用默认初始化,第二个使用值初始化。” 这意味着第一个调用默认构造函数,而第二个创建一个临时对象并使用赋值运算符? @peter.slizik:不。如果类有一个非平凡的默认构造函数,那么两者都会使用它。如果不是,则默认初始化将使 POD 对象未初始化,而值初始化会将它们初始化为零值。两者都不会创建临时或使用分配。 @peter.slizik:有关 C++ 中各种初​​始化类型的更多详细信息,请参阅 this question。 感谢您的链接,我从未听说过这种区别。原因可能就在这里:要意识到“值初始化”是 C++ 2003 标准中的新内容 - 它在 1998 年的原始标准中不存在。【参考方案2】:

因为你不是抛出 new 异常,而是构造它。

考虑以下:

MyException exception = MyException(); // works
MyException exception = MyException; // doesn't work

new MyException; // works
new MyException();// works

【讨论】:

【参考方案3】:

FAQ 中列出的情况不同,此处不适用。

MyException 在第一种情况下只是一个类型名称,在第二种情况下创建一个变量。这只是语法。一样

MyException ex = MyException;

不会编译,但是

MyException ex = MyException();

会的。 FAQ 示例简单地说明了以下内容:

MyException ex();

这确实是一个函数声明,而:

MyException ex;

会的。

没有办法

throw MyException();

MyException ex = MyException();

可以解释为函数声明,因此它们可以工作。

【讨论】:

以上是关于为啥 `throw MyClass' 不起作用而 `throw MyClass()' 起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 /**/ 注释在样式表中起作用,而 // 注释却不起作用?

Linq WHERE EF.Functions.Like - 为啥直接属性起作用而反射不起作用?

为啥 std::unique_ptr 重置与赋值不同?

为啥服务器端数据表在一页中显示所有记录而搜索不起作用?

.push() 在 throw 下不起作用,使用 async await 方法在 javascript 中循环获取数据

为啥正常的 for 循环允许为结构字段分配值,而 for range 在 Golang 中不起作用? [复制]