游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1858|回复: 4

C++问题,谁能告诉我哪里出了错啊!

[复制链接]

5

主题

46

帖子

55

积分

注册会员

Rank: 2

积分
55
QQ
发表于 2007-4-27 19:23:00 | 显示全部楼层 |阅读模式
程序里我定义了一个Clock类;
class Clock
{
private:
    Clock();
    ~Clock();
public:
    static Clock* GetClock()
   {
      static Clock  c;
      return &c;
   }
};
这应该是个单件吧.但为甚么在我的程序里,构造函数调用了两次呢.

奇怪的是,里面有个函数

void Update()
{
    std::list<int> List;       //如果没有这个定义,构造函数调用一次

    for(int i=0; i<4; ++i)     //使用for循环时, 构造函数调用两次
        Clock::GetClock();

    //Clock::GetClock();       //换成这个,构造函数调用了一次
    //Clock::GetClock();
    //Clock::GetClock();
    //Clock::GetClock();
}
[em7] [em7] [em7] [em7]

附带工程文件.

sf_2007427192257.rar

6.5 KB, 下载次数:

6

主题

307

帖子

309

积分

中级会员

Rank: 3Rank: 3

积分
309
发表于 2007-4-27 21:46:00 | 显示全部楼层

Re:C++问题,谁能告诉我哪里出了错啊!

你用了inline的写法
Release对inline进行了优化,你在两个地方调用了GetClock,展开了两次,结果就构造了两次

看看反汇编就知道了

5

主题

46

帖子

55

积分

注册会员

Rank: 2

积分
55
QQ
 楼主| 发表于 2007-4-27 22:11:00 | 显示全部楼层

Re: C++问题,谁能告诉我哪里出了错啊!

有道理,
Debug版,还有去掉优化的Release版都没问题的.
但是为什么不用for循环,就没问题.
前面没有 list<int> List; 又没问题. 和stl有什么关系啊.
好奇怪啊.

6

主题

307

帖子

309

积分

中级会员

Rank: 3Rank: 3

积分
309
发表于 2007-4-28 09:08:00 | 显示全部楼层

Re:C++问题,谁能告诉我哪里出了错啊!

你在main里调用了一次GetClock,在Update里也调用了一次GetClock

两次调用在两个cpp里,也就展开了两次

你的问题不是用不用循环,而是main里的一次调用造成的

36

主题

1047

帖子

1147

积分

金牌会员

Rank: 6Rank: 6

积分
1147
发表于 2007-4-28 10:34:00 | 显示全部楼层

Re:C++问题,谁能告诉我哪里出了错啊!

我分别在 vs2003 和 vs2005sp1 中测试了一下,发现在 2005 中只调用了一次,2003 中确实调用了2次,楼上几位说是由于内联展开的问题造成的,我觉得实际情况还不一定是这样,通过观察 Release 版的汇编代码可以看到,在 2003 中:

        static Clock* GetClock()
        {
                static Clock c;
00401000  mov         cl,byte ptr [`Clock::GetClock'::`2':S1 (4086C4h)]
....
                return &c;
        }

int Update()
{
        std::string name;

        for(int i=0; i<4; ++i)
        {
                Clock::GetClock();
00401066  test        byte ptr [`Clock::GetClock'::`2'::$S3 (4086C8h)],bl
...
        }

        return 0;
}
可以看到 2 处地址并不相同,这是造成调用两次构造函数的主要原因。而在 2005 中:
int main()
{
        Clock::GetClock();       
00401000  mov         eax,1
00401005  test        byte ptr [`Clock::GetClock'::`2'::`local static guard' (403020h)],al
....
        Update();
        return 0;
}

int Update()
{
        std::string name;

        for(int i=0; i<4; ++i)
        {
                Clock::GetClock();
00401070  test        byte ptr [`Clock::GetClock'::`2'::`local static guard' (403020h)],bl
...
        }

        return 0;
}
两处地址完全相同,所以只调用一次构造函数。按照语法来讲,应该调用一次,只要是 static 变量,应该是保存在程序的静态数据空间中,静态数据空间中存储的变量在程序 c++ runtime 调用 main 函数之前就会初始化,而不是等调用到这个函数时才会初始化。所以通过 2003 和 2005 中的不同表现来看,我认为是 2003 编译器的一个缺陷,有可能是个 bug,在 2005 中被修正了。如果把类定义改成如下:
class Clock
{
private:
    Clock();
    ~Clock();
    static Clock c;
public:
    static Clock* GetClock()
   {
       return &c;
   }
};
在 cpp 中声明:
Clock Clock::c;
则在 2003 中是调用了一次,所以由此可见 2003 中对于内联函数内的静态变量的优化是有问题的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-26 15:43

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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