对象切片,矢量元素超出范围
Object slicing, vector element out of scope
我正在尝试在没有对象切片的情况下将派生类存储在向量中。我有一天中的大部分时间都在努力寻找,还没有弄清楚如何让它工作。我读过的解决方案建议存储指向派生对象的指针的实际对象。我无法让它工作,但我想添加这些对象以这样的方式向量,这将导致对象超出之前的范围矢量超出范围。所以,我认为这种解决方案不会奏效无论如何。另一种解决方案建议使基类抽象,但事实并非如此要么工作。我读到了覆盖赋值运算符和副本构造函数,但我认为他们最终没有做任何与正常不同的事情赋值运算符和 noraml 复制构造函数。我用虚拟的尝试过赋值运算符也没有成功。以下是我所经历的一个例子与之合作。main方法中的"vec.emplace_back(&derivedEvent(;"语句导致基类被添加到向量中。紧接着,对象超出范围,向量不再包含派生事件的数据。我是编程仍然很新,所以我尝试的任何事情都可能做错了。
#include <string>
#include <vector>
////////////////////////////////////////////////////////////////////////////////
class CBaseEvent {
protected:
CBaseEvent(){}
std::string m_strBeginning;
std::string m_strEnd;
public:
CBaseEvent(std::string strBeginning, std::string strEnd)
: m_strBeginning(strBeginning), m_strEnd(strEnd){}
};
////////////////////////////////////////////////////////////////////////////////
class CDerivedEvent : public CBaseEvent {
private:
CDerivedEvent(){}
std::string m_strMiddle;
public:
CDerivedEvent(
std::string strBeginning,
std::string strMiddle,
std::string strEnd)
: CBaseEvent(strBeginning, strEnd),
m_strMiddle(strMiddle){}
};
////////////////////////////////////////////////////////////////////////////////
int main() {
std::vector<std::shared_ptr<CBaseEvent>> vec;
if (true) {
CDerivedEvent derivedEvent = CDerivedEvent("1", "2", "3");
vec.emplace_back(&derivedEvent);
}
return 0; //CRASH: possible corruption of the heap
}
您正在堆栈和 if 语句的作用域内创建对象,一旦它超出该作用域,该对象将不再存在,当 share_ptr 被超出 main 函数作用域的向量破坏时,您的程序将崩溃,因为它将尝试销毁不再存在的对象。
这:
if (true) {
CDerivedEvent derivedEvent = CDerivedEvent("1", "2", "3");
vec.emplace_back(&derivedEvent);
}
应该是:
if (true) {
CDerivedEvent* derivedEvent = new CDerivedEvent("1", "2", "3");
vec.emplace_back(derivedEvent);
}
它应该像您期望的那样工作,但正如 Jhon Purdy 在下面的评论中所说,这将更合适:
int main()
{
std::vector<std::unique_ptr<CBaseEvent> > vec;
vec.push_back(std::unique_ptr<CBaseEvent>(new CDerivedEvent("1", "2", "3")));
return 0;
}
我喜欢
std::vector<std::unique_ptr<CBaseEvent> > vec;
AngelCastillo经常使用的方法,但它只有一件事是错误的。
std::unique_ptr<CBaseEvent>(new CDerivedEvent(blah))
将导致通过 CBaseEvent*
类型的指针删除 CDerivedEvent
类型的对象。 由于CBaseEvent
没有虚拟析构函数(它甚至不是多态的(,因此这是未定义的行为。
这可以通过任一方法修复
- 添加虚拟析构函数或
使用
std::shared_ptr
,这将类型信息保留在删除程序内部。std::vector<std::shared_ptr<CBaseEvent> > vec; vec.push_back(std::make_shared<CDerivedEvent>(whatever));
- 使用std::transform将一个范围的元素添加到另一个范围中
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- C++基于范围的 for 循环和元素副本
- 如果变量数据包含大于 vector 所有元素的整数,则仅在视觉工作室上接收"矢量下标超出范围"?
- 如何读/写或遍历 std::array 中的特定元素范围?
- 基于相邻元素 c++ 的分段误差范围的循环
- 是否存在一个范围::视图::group_by对应项,它将所有元素都考虑在内,而不是只考虑连续的元素
- 对于多个查询,查找在 l 到 r 范围内具有相同元素的最长公共子数组
- 我应该如何使用remove_if删除两个数字范围内的元素
- 从给定范围内的向量中查找最大元素
- 忽略元素的基于范围的 for 循环
- 包含每个 k 个列表中至少 1 个元素的最小元素范围的时间复杂度
- 矢量擦除范围内的元素
- 为什么基于范围的循环不修改容器元素?
- 删除重复的元素并给出一个范围总和
- 检查范围的元素是否可以移动?
- 使用对范围中的矢量元素的引用
- 使用其范围版本从容器中删除元素的最佳方法
- 删除矢量中的范围元素(C++)
- 选择OpenGL范围元素GL_ELEMENT_ARRAY_BUFFER