将NULL指针转换为对象并调用其成员函数之一是否有实际好处?

Zol*_*oli 9 c++ null member-functions offset

好的,所以我知道技术上这是未定义的行为,但是,我在生产代码中不止一次地看到过这种情况.如果我错了,请纠正我,但我也听说有些人使用这个"功能"作为当前C++标准缺乏方面的合理替代,即无法获得地址(嗯,成员函数的真正偏移).例如,这不是PCRE(Perl兼容的正则表达式)库的流行实现:

#ifndef offsetof
#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
#endif
Run Code Online (Sandbox Code Playgroud)

人们可以争论在这样的情况下利用这种语言的微妙性是否有效,甚至是必要的,但我也看到过这样使用:

struct Result
{
   void stat()
   {
      if(this)
         // do something...
      else
         // do something else...
   }
};

// ...somewhere else in the code...

((Result*)0)->stat();
Run Code Online (Sandbox Code Playgroud)

这很好用!它通过测试是否存在来避免空指针取消引用this,并且它不会尝试访问else块中的类成员.只要这些警卫到位,这是合法的代码,对吗?所以问题仍然存在:是否有一个实际的用例,人们可以从使用这样的结构中受益?我特别关注第二种情况,因为第一种情况更多是语言限制的解决方法.或者是吗?

PS.对C风格的演员表示抱歉,不幸的是,如果可以,人们仍然喜欢打字.

bma*_*ies 9

第一种情况是没有召唤任何东西.这是在拿地址.这是一个定义的,允许的操作.它产生从对象开始到指定字段的偏移量(以字节为单位).这是一种非常非常常见的做法,因为非常普遍需要这样的偏移.毕竟,并非所有对象都可以在堆栈上创建.

第二种情况是相当愚蠢的.明智的做法是将该方法声明为静态.

  • 人们为什么写错代码?只有原作者才能解释这种滥用语言背后的动机. (4认同)
  • 关于`&`运算符,C99确实说过,"如果操作数是一元`*`运算符的结果,那么运算符和`&`运算符都不会被计算,结果就好像两者都被省略了"(§6.5. 3.2/3).C89,C++ 03和C++ 0x FCD没有任何语言.在任何情况下,虽然这允许`&*a`,其中`a`不指向一个对象,我不认为它允许`&((*a).b)`.我不知道; 我同意,鉴于`offsetof`的这种常见实现,我可能错了; 我只是找不到文件说我错了.希望别人知道的更好.: - / (2认同)