C++ 指向范围外c+的指针复制+;

C++ 指向范围外c+的指针复制+;,c++,pointers,vector,scope,C++,Pointers,Vector,Scope,今天我回去调查一个旧项目中的错误。这并不完全是一个错误,相反,我不知道如何做我需要做的事情。我真的不想进入项目的细节,因为它是旧的、有缺陷的、低效的,更重要的是不相关的。因此,我编写了一个新的示例代码: #include <iostream> #include <vector> #include <time.h> #include <random> #include <string> class myDoc; class myEle

今天我回去调查一个旧项目中的错误。这并不完全是一个错误,相反,我不知道如何做我需要做的事情。我真的不想进入项目的细节,因为它是旧的、有缺陷的、低效的,更重要的是不相关的。因此,我编写了一个新的示例代码:

#include <iostream>
#include <vector>
#include <time.h>
#include <random>
#include <string>

class myDoc;

class myElement
{
    int myInt;
    std::string myString;
    myElement * nextElement;
    //a pointer to the element that comes immediately after this one
public:
    myElement(int x, std::string y) : myInt(x), myString(y){};
    friend myDoc;
};//an element type

class myDoc
{
    std::vector<myElement> elements;
public:
    void load();
    ~myDoc()
    {
        //I believe i should delete the dynamic objects here.
    }
};// a document class that has bunch of myElement class type objects as members

void myDoc::load()
{
    srand(time(0));
    myElement * curElement;
    for (int i = 0; i < 20; i++)
    {
        int randInt = rand() % 100;
        std::string textInt =  std::to_string(randInt);
        curElement = new myElement(randInt,textInt);
        //create a new element with a random int and its string form

        if (i!=0)
        {
            elements[i-1].nextElement = curElement;
            //assign the pointer to the new element to nextElement for the previous element 
            //!!!!!!!!!!!! this is the part that where i try to create a copy of the pointer
            //that goes out of scope, but they get destroyed as soon as the stack goes out of scope
        }

        elements.push_back(*curElement);// this works completely fine
    }
}

int main()
{
    myDoc newDoc;
    newDoc.load();
    // here in newDoc, non of the elements will have a valid pointer as their nextElement
    return 0;
}
#包括
#包括
#包括
#包括
#包括
类myDoc;
类myElement
{
int-myInt;
std::string myString;
myElement*nextElement;
//指向紧跟在该元素之后的元素的指针
公众:
myElement(intx,std::stringy):myInt(x),myString(y){};
我的朋友;
};//元素类型
类myDoc
{
std::向量元素;
公众:
空荷载();
~myDoc()
{
//我认为我应该删除这里的动态对象。
}
};// 一个文档类,其成员是一堆myElement类类型对象
void myDoc::load()
{
srand(时间(0));
myElement*curElement;
对于(int i=0;i<20;i++)
{
int randInt=rand()%100;
std::string textInt=std::to_string(randInt);
CureElement=新的myElement(randInt,textInt);
//使用随机整数及其字符串形式创建新元素
如果(i!=0)
{
元素[i-1]。nextElement=CureElement;
//将指向新元素的指针指定给上一个元素的nextElement
//!!!!!!!!!!!!!!!!!这是我尝试创建指针副本的部分
//这超出了范围,但一旦堆栈超出范围,它们就会被销毁
}
elements.push_back(*curElement);//这工作完全正常
}
}
int main()
{
myDoc newDoc;
load();
//在newDoc中,非元素将有一个有效指针作为其下一个元素
返回0;
}
基本概述:我们有一个文档类型,它由我们定义的元素类型的向量组成。在本例中,我们将20个随机动态分配的新元素加载到文档中。 我的问题:

  • 当函数结束时,指针和/或其副本将超出范围并被删除。我如何保持一个副本(不是完全静态的,是吗?)至少在它指向的对象被删除之前保持不变
  • 元素
    向量中的对象是原始的动态分配对象还是只是副本
  • 我用
    new
    分配内存,我应该如何/何时
    删除它们
  • 下面是我为解释第一个问题而画的一幅图(对于具体的例子来说不是很准确,但问题是相同的),谢谢您的时间。 注意:我假设您想要一个
    myElement
    对象的向量,其中每个对象都指向它旁边的元素。不清楚您是否希望
    元素中的对象指向它们的副本,无论如何,修改代码以实现后者应该非常容易

    这就是代码中发生的情况:

    void myDoc::load()
    {
       ..
       curElement = new myElement(n,m); // Create a new element on the heap
    
       ...
       // If this is not the first element we inserted, have the pointer for the
       // previous element point to the heap element 
       elements[i-1].nextElement = curElement;
    
       // Insert a COPY of the heap element (not the one you stored the pointer to)
       // into the vector (those are new heap elements copied from curElement)
       elements.push_back(*curElement);// this works completely fine
    }
    
    因此,当
    myDoc::load()
    超出范围时,不会删除任何内容,但会出现内存泄漏和错误,因为指针不是指向
    元素
    向量中的元素,而是指向您分配的第一个堆元素

    这也回答了你的第二个问题:它们是复制品

    为了自动释放内存,无泄漏,并指向正确的元素,您可以执行以下操作

    class myElement
    {
      int a;
      std::string b;
      myElement *nextElement = nullptr;
      //a pointer to the element that comes immediately after this one
    public:
      myElement(int x, std::string y) : a(x), b(y){};
      friend myDoc;
    };//an element type
    
    class myDoc
    {
      std::vector<std::unique_ptr<myElement>> elements;
    public:
      void load();
      ~myDoc()
      {}
    };// a document class that has bunch of myElement class type objects as members
    
    void myDoc::load()
    {
      srand((unsigned int)time(0));
      for (int i = 0; i < 20; i++)
      {
        int n = rand() % 100;
        std::string m = std::to_string(n);
        //create a new element with a random int and its string form
        elements.emplace_back(std::make_unique<myElement>(n, m));
    
        if (i != 0)
        {
          //assign the pointer to the new element to nextElement for the previous element 
          elements[i - 1]->nextElement = elements[i].get();
        }
      }
    }
    
    类myElement
    {
    INTA;
    std::字符串b;
    myElement*nextElement=nullptr;
    //指向紧跟在该元素之后的元素的指针
    公众:
    myElement(intx,std::stringy):a(x),b(y){};
    我的朋友;
    };//元素类型
    类myDoc
    {
    std::向量元素;
    公众:
    空荷载();
    ~myDoc()
    {}
    };// 一个文档类,其成员是一堆myElement类类型对象
    void myDoc::load()
    {
    srand((无符号整数)时间(0));
    对于(int i=0;i<20;i++)
    {
    int n=rand()%100;
    std::string m=std::to_string(n);
    //使用随机整数及其字符串形式创建新元素
    元素。向后放置(std::make_unique(n,m));
    如果(i!=0)
    {
    //将指向新元素的指针指定给上一个元素的nextElement
    elements[i-1]->nextElement=elements[i].get();
    }
    }
    }
    


    无需
    删除析构函数中的任何内容,因为当
    myDoc
    元素超出范围时,智能指针将自动销毁(并释放内存)。我相信这可能是您想要做的,因为这些元素归
    myDoc
    类所有。

    请发布-比某个东西的图片好得多。谢谢您的回答,这真的很有帮助。谢谢你的细微的修正。一件小事,当时,这是一个家庭作业项目,我不允许使用智能指针。您认为没有它们的解决方案是可能的/值得研究的吗?@user340283当然,您可以自己分配内存并在析构函数中管理释放。您可以创建一个
    std::vector
    并使元素指向向量中的其他元素(C++11提供就地构造),或者只需使用
    std::vector
    并自行管理所有分配(除了向量中包含的指针)。非常感谢,我现在更了解它。