我有一个类叫做 Controller
,在其中,我有一个名为 Button
的类. Controller
包含几个 Button
不同类型的实例(例如 button_type_a
、 button_type_b
)。
controller.h
#ifndef __controller__
#define __controller__
class Controller
{
public:
class Button
{
public:
Button(int type = -1);
private:
int type;
};
Controller();
Button A;
Button B;
Button X;
Button Y;
};
#endif
按钮类型为 int
s,我希望能够关联某些按钮类型 int
s 指向 Button
这些特定类型的实例。
为了跟踪这个关联,我使用了 std::map<int, Controller::Button*>
,我typedef
到 buttonmap_t
.
当我创建新的 Button
实例(在 Controller
构造函数中), Button
构造函数注册那些 Button
的类型附上 map 。
Controller .cpp
#include "controller.h"
#include <map>
typedef std::map<int, Controller::Button*> buttonmap_t;
buttonmap_t map;
Controller::Controller() :
A(0),
B(1),
X(2),
Y(3)
{ }
Controller::Button::Button(int type) :
type(type)
{
map[type] = this;
}
然后我创建一个全局 Controller
对象,我定义了 main()
.
main.cpp
#include <iostream>
#include "controller.h"
Controller controller;
int main(int argc, const char * argv[])
{
std::cout << "running..." << std::endl;
return 0;
}
根据我编译源代码的顺序,程序要么运行良好,要么触发段错误:
apogee:MapTest$ gcc controller.cpp main.cpp -o maptest -lstdc++
apogee:MapTest$ ./maptest
running...
apogee:MapTest$ gcc main.cpp controller.cpp -o maptest -lstdc++
apogee:MapTest$ ./maptest
Segmentation fault: 11
似乎后一种情况是在正确初始化之前尝试使用 map ,这会导致段错误。当我使用 Xcode 进行调试时,调试器在“__tree”中停止为 std::map
正在调用 __insert_node_at()
, 抛出 EXC_BAD_ACCESS(code=1, address=0x0)
.调用堆栈显示这是由第一个 Button
触发的实例调用 map[type] = this;
.
那么,这是我的多部分问题:
- 为什么编译顺序会导致这种情况发生?
- 有没有办法实现这种
int
至Button*
不受影响的映射 编译顺序? - 如果是,那是什么?
理想情况下,我仍然希望拥有所有 Controller
- 和 Button
- 单独 Controller 中的相关代码。*文件。
这似乎与以下问题有些相关(但不完全相同):
最佳答案
当你有多个全局构造函数时,它们的执行顺序是不确定的。如果 controller
对象在 map
对象之前实例化, Controller 将无法访问该映射,从而导致段错误。但是,如果 map
对象首先被实例化,那么 Controller 就可以很好地访问它。
在这种情况下,它似乎是它们在命令行中出现的顺序。这就是为什么将 main.cpp
放在第一位会导致段错误 - controller
对象首先被实例化。
我建议将实例化移动到您的 main
中,因为这样您就可以准确地控制对象的实例化方式和顺序。
关于c++ - 为什么在使用 std::map::insert() 时编译顺序有时会导致段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17623815/