查看: 651|回复: 2
收起左侧

请教一下为什么这个singleton不会报错?

|只看干货 |技术交流
本楼: 👍   0% (0)
 
 
0% (0)   👎
全局: 👍   96% (31)
 
 
3% (1)    👎

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看,没有帐号?注册账号

x
本帖最后由 a840240760 于 2021-4-21 01:03 编辑

昨晚在看cherno的c++ tutorial,他随手写了一个singleton,我看了之后觉得不太对然后自己写了一遍,发现还真不会报错,但不太理解为什么不会报错

[Bash shell] 纯文本查看 复制代码
#include <iostream>

using namespace std;

class Singleton {
  private:
    static Singleton* instance;

  public:
    static Singleton& getInstance() {
      return *instance;
    }

    void hello() {
      cout << "Hello" << endl;
    }
};

Singleton* Singleton::instance = nullptr;

int main() {
  if (&Singleton::getInstance() == nullptr) {
    // "Yes" will be printed
    cout << "Yes\n";
  }
  // also "Hello" will be printed
  Singleton::getInstance().hello();
  return 0;
}


我在前面已经把instance设成了nullptr,这样为什么在getInstance的时候不报错呢?我在reddit上提问有人回答说是Undefined Behavior, 我理解UB有时会工作有时不会,但是具体哪一部分是undefined behavior呢?

PS:这个问题并非关于singleton最佳实践,我仅仅好奇为什么这样写不会报错,多谢!

上一篇:Outlook IOS端一直闪退
下一篇:Python/Pandas/Dataframe 如何删除所有非重复项/非重复row?
lalxyy 2021-4-24 14:10:35 | 显示全部楼层
本楼: 👍   100% (2)
 
 
0% (0)   👎
全局: 👍   99% (1136)
 
 
0% (9)    👎
本帖最后由 lalxyy 于 2021-4-24 01:19 编辑

楼主可以多运用一下godbolt这个工具,能够辅助理解一些语法是怎样编译为汇编语言的。楼主的main函数在x86-64 gcc 10.3是这样的编译结果(-O0):

[Bash shell] 纯文本查看 复制代码
main:
        push    rbp
        mov     rbp, rsp
        call    Singleton::getInstance()
        test    rax, rax
        sete    al
        test    al, al
        je      .L5
        mov     esi, OFFSET FLAT:.LC1
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
.L5:
        call    Singleton::getInstance()
        mov     rdi, rax
        call    Singleton::hello()
        mov     eax, 0
        pop     rbp
        ret


所以第22行虽然有一个先dereference再reference的过程,但是整个表达式并不是一字一句反映到汇编中,也就是被gcc处理掉了。最后的汇编接近nonsense(因为寄存器自己和自己test,也就是做and操作,最后不会对寄存器的值有任何变化)。这个是undefined behavior,换一个架构换一个编译器是不能保证同样的行为的。第27行也是如此,因为hello()不涉及this pointer,编译器也很有可能把hello直接当static所以可以正常执行,这个同样是undefined behavior.
回复

使用道具 举报

 楼主| a840240760 6 天前 来自APP | 显示全部楼层
本楼: 👍   0% (0)
 
 
0% (0)   👎
全局: 👍   96% (31)
 
 
3% (1)    👎
lalxyy 发表于 2021-04-23 23:10:35
楼主可以多运用一下godbolt这个工具,能够辅助理解一些语法是怎样编译为汇编语言的。楼主的main函数在x86-64 gcc 10.3是这样的编译结果(-O0):

main:
多谢!请问寄存器和自己比较那一段属于UB吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

隐私提醒:
■拉群请前往同学同事飞友|拉群结伴版块,其他版块拉群,帖子会被自动删除
■论坛不能删帖,为防止被骚扰甚至人肉,不要公开留微信等联系方式,请以论坛私信方式发送。
■特定版块可以超级匿名:https://tools.1point3acres.com/thread
■其他版块匿名方法:http://www.1point3acres.com/bbs/thread-405991-1-1.html

>
快速回复 返回顶部 返回列表