超出范围后,矢量数据会丢失

时间:2018-01-06 20:41:09

标签: c++ pointers vector forward-list

我正在开发一个项目,我将前向列表和向量一起使用并输出它们的值。转发列表是Frame个对象的列表,向量是Display个对象的向量。问题是在InsertFrame()中创建对象之后,向量的值会丢失并且基本上变成垃圾。我可以在调试器中看到它在函数结束后发生,这使我相信它与超出范围的变量有关。这是主要的创作类

// Animation.cpp


#include <crtdbg.h>
#include <iostream>
#include <string>
#include <vector>
#include <forward_list>
using namespace std;

#include "Display.h"
#include "Frame.h"
#include "Animation.h"
#include "GPUMemoryDisplay.h"
#include "SystemMemoryDisplay.h"


    void Animation::InsertFrame() {

        int numDisplays;        //for user input of display number
        vector <Display*>v;     //vector for containing display objects
        int p_x;                //will contain user input for pixel_x
        int p_y;                //will contain user input for pixel_y
        int p_duration;         //will contain user input for duration
        int p_type ;            //will contain display type as int value
        char * p_name;          //temp string to contain user input for name
        string d_name;          //will contain p_name to be passed to display constructor
        string frameName;       //contains user input for the frame name
        string gpu_shader;      //contains gpu name if gpu type is selected
        int q = 0;              //used to count the diplay #

        //begin reading user input
        cout << "Insert a Frame in the Animation\nPlease enter the Frame filename: ";
        cin >> frameName;
        cout << "Entering the Frame Displays (the sets of dimensions and durations) " << endl;
        cout << "Please enter the number of Displays: ";
        cin >> numDisplays;

        //display creation loop for # of displays entered
        while (numDisplays > 0) {
            cout << "Please enter pixel x-width for Display #" << q << " pixel_x:";
            cin >> p_x;
            cout << "Please enter pixel y-width for Display #" << q << " pixel_y:";
            cin >> p_y;
            cout << "Please enter the duration for this Display: ";
            cin >> p_duration;
            cout << "Please enter the name for this Display: ";
            cin >> d_name;
            cout << "Please enter the type for this display (1 = SystemMemoryDisplay, 2 = GPUMemoryDisplay): ";
            cin >> p_type;
            p_name = new char[d_name.length() + 1]; //allocate for the size of the name entered
            strcpy(p_name, d_name.c_str()); //copy string to char []

            if (p_type == 2) {
                //input for GPU shader
                cout << "Please enter the file name of the associated GPU Shader: ";
                cin >> gpu_shader;
                Display *gpu_p = new GPUMemoryDisplay(p_x, p_y, p_duration, p_name, gpu_shader);
                v.push_back(static_cast <Display*>(gpu_p)); //casting to a display* and pushing onto the vector
                numDisplays--;
                q++;
            }
            else {
                Display *sm_p = new SystemMemoryDisplay(p_x, p_y, p_duration, p_name);
                v.push_back(static_cast <Display*>(sm_p));//casting to a display* and pushing onto the vector
                numDisplays--;
                q++;
            }
            cout << "\n";
        }


        Frame t_frame = Frame(frameName, v); //new frame holds vector which contains displays


        //check if forward list is empty
        if (frames.empty()) {
            cout << "\nThis is the first Frame in the list \n\n";
            frames.push_front(t_frame);
        }
        else {
            forward_list <Frame>::iterator it;
            int x = 0; // used for size of current forward_list
            //iterate forward list to obtain the size
            for (it = frames.begin(); it != frames.end(); ++it) {
                x++;
            }
            if (x == 1) {
                it = frames.begin();
                frames.insert_after(it, t_frame);
            }
            else {

                cout << "There are " << x << " Frame(s) in the list\n" << "Please specify the position, between 0 and " << x << " to insert after : ";
                cin >> x; //read in where user wants to put the frame

                //iterate to desired position and insert
                forward_list <Frame>::iterator it;
                it = frames.begin();
                while (x != 0 && it != frames.end()) {
                    it++;
                    x--;
                }
                frames.insert_after(it, t_frame);
            }
        }
    }

框架和显示的标题/ cpp文件

// Frame.h
#pragma once

    class Frame
    {
        string fileName;
        vector<Display*> displays; 
    public:
        Frame(string s, vector<Display*> d) :fileName(s), displays(d) {}
        Frame(const Frame&);
        ~Frame()
        {
            vector<Display*>::iterator it;
            for (it = displays.begin(); it != displays.end(); it++)
                delete *it;
        }
        friend ostream& operator<<(ostream&, Frame&);
    };

 #pragma once
// Display.h

    class Display
    {
    protected:  // accessible to derived classes
        int pixel_x;
        int pixel_y;
        int duration;
        char* name;
    public:
        Display(int x, int y, int duration, char* name);
        Display(const Display&);
        virtual ~Display() //makes class abstract, cannot be instantiated, most general class
        {
            if (name)
                delete[]name;
        }
        virtual int BufferSize() = 0; // overridden function Polymorphic function
        friend ostream& operator<<(ostream&, Display&);
    };

// Display.cpp

#include <crtdbg.h>
#include <iostream>
#include <string>
#include <vector>
#include <forward_list>
using namespace std;
#include "Display.h"
#include "GPUMemoryDisplay.h"

Display::Display(int x, int y, int d, char* n) :pixel_x(x), pixel_y(y), duration(d), name(n) {
}


Display::Display(const Display& p) {
    //copy values from p
    pixel_x = p.pixel_x;
    pixel_y = p.pixel_y;
    duration = p.duration;
    size_t len = strlen(p.name);
    name = new char[len + 1];
    strcpy(name, p.name);
    //cout << pixel_x << pixel_y << duration << name;

}

我有两个名为GPUMemoryDisplay和SystemMemoryDisplay的子类,但我相信部分代码很好,因为我可以看到它们的值在调试器中正确存储。以下是以防万一。

#pragma once
// SystemMemoryDisplay.h

class  SystemMemoryDisplay : public Display
{
public:
    SystemMemoryDisplay(int x, int y, int duration, char* name) :Display(x, y, duration, name) {};
    SystemMemoryDisplay(const SystemMemoryDisplay& RGMD) :Display(RGMD) {}
    int BufferSize() { return pixel_x*pixel_y * sizeof(double); }
}; 


#pragma once
//GPUMemoryDisplay.h
//this is the derived class of display
class GPUMemoryDisplay : public Display
{
    string shader;
public:
    GPUMemoryDisplay(int x, int y, int duration, char* name, string shader) :Display(x, y, duration, name), shader(shader) {};
    GPUMemoryDisplay(const GPUMemoryDisplay& RGPUMD) :shader(RGPUMD.shader), Display(RGPUMD) {}
    string GetShader() { return shader; }
    int BufferSize() { return pixel_x*pixel_y * sizeof(float); } //this is the overridden function from Display class
};

总之,我有一个前向的帧列表,每个帧都可以包含一个Display对象的向量。但是,当InsertFrame()函数退出时,显示数据将丢失。

1 个答案:

答案 0 :(得分:2)

一旦堆栈分配的Frame t_frame = Frame(frameName, v);对象超出范围,它们的析构函数就会被调用,并将删除存储在Frame::displays中的指针所指向的所有对象。您需要实现适当的复制和/或移动构造函数和赋值运算符,以便正确地传递这些指针。您应该使用::std::unique_ptr来保留已分配对象的所有权,而不是使用原始指针并手动删除它们,并::std::string来管理字符串而不是指向char的原始指针。同时将using namespace std;置于中间包含也不好,如果你打算在包括之后至少使用