在main()消失之前初始化的值

ShP*_*vel 5 c++

无法理解奇怪的程序行为 - 希望有人可以解释.

dummy.h:

#ifndef DUMMY_H
#define DUMMY_H

#include <iostream>

class Dummy
{
    int val;

public:
    int Init(int new_val)
    {
        return val = new_val;
    }

    int Get()
    {
        return val;
    }

    Dummy():
        val(-1)
    {
        std::cout << "constructed" << std::endl;
    }

    ~Dummy()
    {
        std::cout << "deconstructed" << std::endl;
    }
};

#endif /*DUMMY_H*/
Run Code Online (Sandbox Code Playgroud)

header.h:

#include "dummy.h"

extern Dummy dummy;
Run Code Online (Sandbox Code Playgroud)

dummy.cpp:

#include "dummy.h"

Dummy dummy;
Run Code Online (Sandbox Code Playgroud)

main.cpp中:

#include <iostream>

#include "header.h"

int res1 = dummy.Init(2);
int res2 = dummy.Get();

int main()
{
    std::cout << res1 << std::endl;
    std::cout << res2 << std::endl;
    std::cout << dummy.Get() << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译: g++ -Wall -Wextra main.cpp dummy.cpp

输出:

constructed
2
2
-1
deconstructed
Run Code Online (Sandbox Code Playgroud)

为什么在main()函数中调用的第二个Get()返回-1?为什么指定的值从虚拟实例中消失,并且没有调用解构函数.怎么变成-1?

upd:将调试信息添加到Init()和Get():

新产出:

init
get
constructed
2
2
get
-1
deconstructed
Run Code Online (Sandbox Code Playgroud)

upd2:有趣的事实 - 在一个可执行文件中单独编译和链接目标文件改变了这种情况:

g++ -c dummy.cpp 
g++ -c main.cpp 
g++ dummy.o main.o 

./a.out

constructed
init
get
2
2
get
2
deconstructed
Run Code Online (Sandbox Code Playgroud)

但这是陷阱!

jro*_*rok 10

未指定在不同翻译单元中初始化全局变量的顺序.无论是dummy或两个全球int在main.cpp的小号可以首先构建.

根据你的情况,这是res1和res2那得到了第一次初始化,所以你通过调用尚未修建了对象的成员函数调用未定义的行为.

要修复它,请尝试以下方法:

header.h:

#include "dummy.h"

Dummy& getDummy();
Run Code Online (Sandbox Code Playgroud)

dummy.cpp:

#include "dummy.h"

Dummy& getDummy()
{
    static Dummy dummy; // gets initialized at first call
                        // and persists for the duration of the program
    return dummy;
}
Run Code Online (Sandbox Code Playgroud)

main.cpp中

int res1 = getDummy().Init(2);
int res2 = getDummy().Get();
Run Code Online (Sandbox Code Playgroud)

如果有帮助的理解,加上一些调试COUT语句Get和Init也.您所经历的也称为静态初始化顺序惨败.

  • @ShPavel未定义行为的一个可能结果是它看起来有效. (5认同)