std :: vector不保留在实现中实例化的推回对象

时间:2016-03-21 14:51:32

标签: c++ vector scope implementation

我有一个向量和一个在plane.h中声明的对象:

extern Plane Default;
extern std::vector<Plane *>universe;

它们在plane.cpp中定义:

Plane Default("Default");
std::vector<Plane *>universe;

平面构造函数:

Plane::Plane(const std::string &label) {
    /* check universe to ensure uniqueness */
    std::cout << this << std:endl; //DEBUG CHECK to see what I push_back

    universe.push_back(this); //ACTION to keep track of the planes

    std::cout << universe.back() << std::endl; //DEBUG CHECK to ensure that it was stored correctly
}

输出确认平面确实存储在矢量中。

主要:

if(universe.empty()) cout << "EMPTY UNIVERSE" << endl;

表示向量未保留该值。我希望Default(在plane.cpp中定义)存储在Universe中。

Demo

但是,当我从main

实例化平面时,Universe会保留这些值

我想它与本地副本,范围和值传递有关,但我无法找到一种方法来实例化实现中的默认平面,以便它的地址保存在向量中。

我也试过从堆中声明向量,如下所示:

extern std::vector<Plane *> *universe;

并定义如下:

std::vector<Plane *> *universe = new std::vector<Plane *>;

它刚刚破坏了程序。 我在64位Vista机器上使用MinGW32 4.9代码:块16.01和-std = C ++ 11

3 个答案:

答案 0 :(得分:5)

您点击全局初始化顺序fiasco:

Plane Default("Default");
std::vector<Plane *>universe;

Default依赖universe,但当构造Default时,universe尚未构建。

这就是你应该避免全球化的原因。

假设存在相同的翻译单元,您的案例中的解决方法是更改​​顺序:

std::vector<Plane *>universe;
Plane Default("Default");

答案 1 :(得分:1)

answer by Jarod42应解决您遇到的问题。我将提供一些指导来防止这些问题。

通常,最好避免使用extern声明变量访问的全局数据。最好使用功能接口提供对全局数据的访问。

您可以更改

extern std::vector<Plane *>universe;

extern std::vector<Plane *>& getUniverse();

并将其实施为:

extern std::vector<Plane *>& getUniverse()
{
   static std::vector<Plane *>universe;
   return universe;
}

有了这个,您可以将Plane的构造函数更改为:

 Plane::Plane(const std::string &label) {
    getUniverse().push_back(this);
}

这将消除与全局数据初始化顺序相关的问题。

您也可以更改

extern Plane Default;

extern Plane& getDefaultPlane();

并将其实现为

extern Plane& getDefaultPlane()
{
   static Plane Default("Default");
   return Default;
}

如果必须在初始化时构造默认Plane,您可以使用以下内容:

// Use a helper struct in an anonymous namespace to initialize
// whatever needs to be initialized.
namespace
{
    struct Initializer
    {
       Initializer();
    };
}

// Make sure that Initializer::Initializer() gets called
// at initialization time.
static Initializer initer;

Initializer::Initializer()
{
   // Trigger construction of the default Plane
   getDefaultPlane();
}

答案 2 :(得分:0)

如果你的指针范围有问题,或许使用shared_ptr就足够了?但是,如果您担心指针的持久性可能被删除或移动并且仍然需要数据,我不知道您的整体设计;一个智能指针可能是答案。如果在任何地方出现循环问题,请使用weak_ptr来打破它。

祝你好运!