为什么不将对象推送到此向量(当它是结构的成员时)?

时间:2010-10-30 19:16:34

标签: c++

我有以下代码,它循环遍历menuoptions数组,并在每次迭代时创建一个ScaledRect对象并将其推送到向量。此向量是结构的成员。

我已经验证了ScaledRect是使用正确的值创建的,但是当我打印回regions向量的内容(在第二个循环中)时,循环永远不会终止并且值是垃圾。

class ScaledRect : public Rect
{
public:
    ScaledRect(int x1, int y1, int x2, int y2);
};
ScaledRect::ScaledRect(int x1, int y1, int x2, int y2):
    _x1(x1), _y1(y1), _x2(x2), _y2(y2){}

// ScaledRect doesn't have copy constructor, but Rect does
Rect::Rect( const Rect &rect)
{
x1=rect.x1; y1=rect.y1; x2=rect.x2; y2=rect.y2; bClean=KD_FALSE;
}

typedef struct
{
    std::vector<ScaledRect> regions;
}interface;

void PushRegions( interface * myself )
{
    int i = 0;
    while(menuoptions[i].callback != -1 )
    {
        ScaledRect s = 
          ScaledRect(menuoptions[i].x1, 
                     menuoptions[i].y1,
                     menuoptions[i].x2, 
                     menuoptions[i].y2);            
        myself->regions.push_back( s );
        i++;
    }

    std::vector<ScaledRect>::iterator iter = myself->regions.begin();
    std::vector<ScaledRect>::iterator done = myself->regions.end();

    while(iter != done)
    {
        iter->Dump();
        iter++;
    }
}

EDIT 请注意 - 我刚编辑了 - theinterface的内存已创建,我确实将theinterface的地址传递给此函数。 (但是,我在这里简化了这两行 - 实际发生的是PushRegions通过ptr调用函数,在一块新分配的内存上调用interface的大小。

我不能在这里发布所有代码 - 但最低限度是:

Func pfunc = GetPFuncForInterfaceObj();
size_t  numbytes = GetSizeForInterfaceObj();
char memory = new char[numbytes];
pfunc(memory);

pfunc最终为PushRegionsmemory最终作为interface传递。

当我将ScaledRect对象推送到vector顶部声明的PushRegions()时,它可以正常工作。有没有人有任何想法?

3 个答案:

答案 0 :(得分:2)

您似乎没有在i函数中初始化PushRegions()。你确定它从0开始吗?

对您的修改进行跟进

  

实际发生的事情是PushRegions通过ptr调用函数,在一块新分配的内存中调用接口的大小

这是什么意思?你实际上是在调用interface构造函数吗?

跟进您的评论

是的,有一个(编译器生成的)构造函数。 std::vector数据成员具有默认构造函数,由编译器生成的interface构造函数调用。当你分配适当数量的内存而不调用构造函数时,你得到一个未初始化的std::vector

这解释了为什么你的循环永远不会终止并且垃圾结果:你正在使用未初始化的对象,这会导致未定义的行为

答案 1 :(得分:1)

这是完全错误的:

size_t  numbytes = GetSizeForInterfaceObj();
char memory = new char[numbytes];
pfunc(memory);

即使我们“修复”它:

size_t  numbytes = GetSizeForInterfaceObj();
char* memory = new char[numbytes]; // note pointer
pfunc((interface*)memory); // and cast

您的对象从未构造过,因此向量处于垃圾状态。 (使用该对象会导致未定义的行为。)

不,interface可能没有明确定义的构造函数,但是有一个隐式构造函数,并且它存在原因。它需要构建成员。您可以使用“placement new”(通过包含<new>)来构建对象,方法是将其放在内存位置:

size_t  numbytes = GetSizeForInterfaceObj();
char* memory = new char[numbytes]; // note pointer
pfunc(new (memory) interface); // and CREATE

现在你正在使用一个有效的对象。


我假设有一个很好的理由使用指针,更不用说手工构造的对象了。也就是说,你的代码做得太多了。它管理资源,而使用一个;选择其中一个。

那是:

struct interface_obj
{
    interface_obj() :
    mMemory(GetSizeForInterfaceObj()),
    mInterface(new (&mMemory[0]) interface)
    {}

    ~interface_obj()
    {
        mInterface->~interface(); // destruct
    }

    interface* get() const
    {
        return mInterface;
    }

private:
    // noncopyable for now, easy to add
    interface_obj(const interface_obj&);    
    interface_obj& operator=(const interface_obj&);

    // again, with the vector we use a resource (dynamic buffer),
    // not manage one.
    std::vector<char> mMemory;
    interface* mInterface;
};

更清洁:

interface_obj obj;
pfunc(obj.get());

它将被发布无论。 (你的代码不会面对异常,没有凌乱的try-catch块和其他废话。)同样,最好是首先不要进行这种分配。

答案 2 :(得分:0)

很难说没有看到ScaledRect的其余内容 - 它是否有一个工作的复制构造函数和赋值运算符? Dump做了什么?

Especailly - 为什么i未初始化?这是(所有)(当前)代码吗?