我有以下代码,它循环遍历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
最终为PushRegions
,memory
最终作为interface
传递。
当我将ScaledRect
对象推送到vector
顶部声明的PushRegions()
时,它可以正常工作。有没有人有任何想法?
答案 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
未初始化?这是(所有)(当前)代码吗?