2015-12-06 2 views
1

Сегодня я вернулся и исследовал ошибку, которую я получил в старом проекте. Это не совсем ошибка, скорее, я не знаю, как делать то, что мне нужно делать. Не хотите вдаваться в детали проекта, поскольку он старый, багги и неэффективен и, что более важно, не имеет значения. Поэтому я закодировал новый образец кода:Указатель Копировать в область видимости C++

#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; 
} 

Basic изношенном: мы имеем тип документа, который состоит из вектора типа элемента мы определяем. И в этом примере мы загружаем в документ 20 случайных динамически выделенных новых элементов. Мои вопросы/проблемы:

  1. Когда функция void myElement::load() заканчивается, указатель и/или копии он выходит из области видимости и удаляются. Как сохранить копию, которая остается (не совсем статичной, не так ли?) По крайней мере до тех пор, пока объект, на который он указывает, не будет удален?
  2. Объекты в векторе elements, являются ли они исходными динамически выделенными объектами или являются ли они просто копией?
  3. Я выделяю память new, как/когда должен i delete их?

Вот фотография, которую я нарисовал, чтобы объяснить 1-ю проблему (не очень точный для конкретного примера, но проблема такая же), и спасибо за ваше время. Here is a picture i made to visualize my main problem.

+0

Пожалуйста, напишите [минимальный, полный и проверенный пример] (http://stackoverflow.com/help/mcve) - настолько лучше, чем картина того или иного. –

ответ

1

Примечание: Я предположил, что вы хотите, вектор myElement объектов, где каждая из них указывает на элемент рядом с ним. Неясно, если вы хотите, чтобы объекты в elements, чтобы указать на их копии, в любом случае это должно быть довольно легко изменить код для достижения последнего

Это то, что происходит в вашем коде:

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() выходит из области видимости, но у вас есть утечки памяти и ошибки поскольку указатели не указывают на элементы в векторе elements, но в первых элементов кучи вы выделенных.

Это также отвечает на ваш второй вопрос: они являются копиями.

Для того, чтобы автоматически освободить память, не имеют утечек и точку вправо элементы, которые вы могли бы сделать что-то вроде

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(); 
    } 
    } 
} 

Live Example

Нет необходимости delete что-либо в деструкторе, поскольку умные указатели будут автоматически уничтожены (и освобождены память), когда элемент myDoc выйдет из области видимости. Я считаю, что это может быть то, что вы хотели сделать, поскольку элементы принадлежат классу myDoc.

+0

Спасибо за ваш ответ, это было действительно полезно. Благодарим вас за тонкие исправления. Одна маленькая вещь, в то время, это был проект домашней работы, и мне не разрешили использовать умные указатели.Считаете ли вы, что решение без них возможно/заслуживает расследования? – user3402183

+0

@ user3402183 уверен, вы, очевидно, можете выделить память самостоятельно и управлять освобождением в деструкторе. Вы можете либо создать «std :: vector » и указать, что эти элементы указывают на другие элементы в векторе (C++ 11 предлагает встроенную конструкцию), либо просто пойти с 'std :: vector ' и управлять всеми выделениями (кроме указателей, содержащихся в векторе) –

+0

Большое спасибо, теперь я понимаю это лучше. – user3402183

Смежные вопросы