- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在研究最近的一个问题时,我发现了 '03 标准[1] 中的以下条款:
When typeid is applied to an lvalue expression whose type is a polymorphic class type (10.3), the result refers to a type_info object representing the type of the most derived object (1.8) (that is, the dynamic type) to which the lvalue refers. If the lvalue expression is obtained by applying the unary * operator to a pointer and the pointer is a null pointer value (4.10), the typeid expression throws the bad_typeid exception (18.5.3).
具体来说,我想知道最后一位,它为取消引用空指针的结果提供了明确定义的行为。据我所知,这是唯一一次这样做[2]。具体来说,dynamic_cast<T&>
对于这种情况没有特殊处理,这似乎是一个更有用的场景。双重考虑dynamic_cast<T&>
已经定义为在某些情况下抛出异常。
是否有特定原因对该特定表达进行特殊处理?这似乎完全是武断的,所以我猜他们想到了一些特定的用例。
[1] '11 中存在类似的子句,但它指的是左值表达式,而不是左值表达式。
[2] delete 0;
和 dynamic_cast<T*>(0)
接近了,但在这两种情况下,您都在处理指针值,而不是实际对象。
最佳答案
如果我更关注下一个子句 (5.2.8/3),我会看到这个
When typeid is applied to an expression other than an lvalue of a polymorphic class type, . . . The expression is not evaluated.
换句话说,与 sizeof
(以及 C++11 中的其他内容)一样,编译器并不意味着实际运行您传递给 typeid
的代码,它只是应该分析它的行为。不幸的是,与 sizeof
不同,由于多态类型,结果有时取决于表达式的运行时行为。
Base* p1 = new Derived;
Base* p2 = new Base;
typeid(*p1); //equivalent to typeid(Derived) [assuming Base is polymorphic]
typeid(*p2); //equivalent to typeid(Base)
如果表达式完全未计算,则编译器无法检查 RTTI 以查看 p1
实际上指向 Derived
而不是 Base
。然而,标准编写者决定更进一步,并声明如果表达式最终是指针类型的取消引用,编译器应该只对它进行部分评估。如果指针为空,则抛出 std::bad_typeid
而不是执行取消引用并引入未定义的行为。
将其与 dynamic_cast
进行对比。传递给 dynamic_cast
的表达式总是被完全评估,否则结果将毫无意义。由于无论如何都要求编译器对表达式进行全面评估,因此指示它提前停止并引发异常是没有意义的。
简而言之,这是给予特殊处理的方式与 sizeof(*(int*)0)
给予特殊处理的方式大致相同。 *(int*)0
并不意味着要被评估,因此没有理由首先引入未定义的行为,即使它看起来很糟糕。
关于c++ - 取消引用 typeid 中的空指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6028427/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我在64位linux下使用c++,编译器(g++)也是64位的。当我打印某个变量的地址时,例如一个整数,它应该打印一个 64 位整数,但实际上它打印了一个 48 位整数。 int i; cout <<
我是一名优秀的程序员,十分优秀!