向量迭代器在赋值重载中不兼容
Posted
技术标签:
【中文标题】向量迭代器在赋值重载中不兼容【英文标题】:Vector iterators incompatible in assignment overload 【发布时间】:2013-09-07 16:30:05 【问题描述】:这里的问题很简单。我在这里用向量处理一些赋值问题。 我有一门课,Inventory:
class Inventory
public:
__inline void operator=( const Inventory& rtSide )
items.clear();
for(auto it=rtSide.items.begin(); it!=rtSide.items.end(); ++it)
items.push_back(*it);
private:
std::vector<void*> items;
有一个包含类的结构:
typedef struct
Inventory *inventory;
player_t;
在 player_t 的指针上分配/执行指针数学运算时,会调用 Inventory 的 = 重载,正如您所期望的那样。但是,使用 MSVC,似乎存在断言失败,特别是“向量迭代器不兼容”。奇怪的是,这发生在 clear() 上。我不知道这里发生了什么。如果有人能给我一些帮助,那就太好了。
下面是一个例子。使用指针数学,我们可以通过从基数中减去当前客户端的播放器结构来确定客户端编号:
clientNum = newcl - svs.clients;
这正是导致我断言的原因。
【问题讨论】:
你知道items.clear()
是做什么的吗?你的循环没有运行。
请提供SSCCE。
rtSide.items.begin() , items 是一个私有变量,可以像这样直接访问?
@jayadev:是的,A 类可以访问其他 A 类实例的私有成员。 Private 只表示“其他类不能碰这个”。这与类的实例无关。
在不知道您使用哪个编译器的情况下:__inline
(很可能)是不必要的。 a) 在他们的类中定义的成员函数总是inline
,b) 认可的关键字是inline
。
【参考方案1】:
我怀疑您的指针运算导致尝试调用Inventory
上的赋值运算符,但实际上指针并未指向Inventory
。 (例如它可能指向delete
'd Inventory
)如果是这样,vector
的胆量可能会被随机垃圾填满,这可能会导致此类断言失败。
例如,您的调用者可能会做以下道德等价行为:
Inventory out;
Inventory* target = nullptr;
*target = out;
这可能会导致此类断言失败。检查调用赋值运算符的代码。
(还请注意,您的赋值运算符不处理对 self 的赋值;但在这种情况下,它只会清除 Inventory
,不会导致断言失败)
【讨论】:
看起来是这样。感谢您的提示!【参考方案2】:我很确定您要复制 rtSide
列表中的项目,而不是 this
中的项目。
items.clear();
for(auto it=rtSide.items.begin(); it!=rtSide.items.end(); ++it)
items.push_back(*it);
(当然,如果你不自己写operator=
,编译器会为你生成这段代码,你也可以通过items = rtSide.items;
复制一个向量——我在帖子中的意思是更多地指出“你的迭代器没有问题,你只是没有复制正确的东西”)。
我还要说,使用vector<void *>
几乎是“以 C 方式使用 C++”。您应该至少存储一个指向基类的指针,如果不是指向基类的智能指针。基类可能是“inventry_item”之类的东西。
(而且我相信 xxxx_t
类型是为 POSIX 保留的,所以你不应该真正调用你的类型 xxxx_t
)
【讨论】:
或者只是items = rtSide.items;
或者更好,让编译器生成的赋值运算符来做它的事情:)
谢谢,我会修改的。但是,这并不能解决问题。它仍然断言 items.clear();
它必须是一个更完整的例子——可以在我的机器(或其他人的机器)上编译的东西。
(当然,“reserved for posix”仅在您以 posix 为目标时才相关。C 和 C++ 都没有保留任何此类内容)
@BillyONEal:这可能是真的,但您永远不知道在您最初考虑的环境之外的其他环境中何时/何时“需要”您的代码。更重要的是,如果您将其作为一种习惯,您可能会在它确实针对 posix 系统的地方不假思索地这样做。以上是关于向量迭代器在赋值重载中不兼容的主要内容,如果未能解决你的问题,请参考以下文章