Владение моим новым Unique_ptrs?

В соответствии с предложением, которое я недавно дал на собеседовании, мне посоветовали изучить функциональность unique_ptr в C ++ 11 в качестве средства автоматического сбора мусора. Поэтому я использую старый проект и заменяю свои необработанные указатели на объекты, созданные с помощью ключевого слова «new», на unique_ptrs. Однако я думаю, что я пришел к вопросу о праве собственности.

В моем mainclass.cpp (опубликованном ниже), пожалуйста, обратите ваше внимание на функцию init, а 3 unique_ptrs — на новые объекты, которые я создал. Названы «bg», «bg2» и «theGrid».
(Закомментированные объявления под ними, как они делали раньше, и переключаясь обратно на этот метод, программа работает просто отлично.)

Однако, используя unique_ptrs, строку в функции void display ():

theGrid->doGridCalculations();//MODEL

генерирует нарушение доступа. Это также первый раз в последовательности, когда любой из указанных объектов разыменовывается, что приводит меня к мысли, что право собственности на unique_ptr уже где-то потеряно. Однако сами unique_ptr никогда не передаются в другую функцию или контейнер и остаются в области действия mainclass.cpp, и поэтому я не видел возможности использовать std :: move (theGrid) для передачи права собственности туда, где это необходимо быть.

Mainclass.cpp:

#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include "Block.h"#include "dStructs.h"#include "Grid.h"#include "Texture.h"#include "freetype.h"#include <Windows.h>//////////////////////////////////////////////////////
///Declare a couple of textures - for the background
//////////////////////////////////////////
Texture* bg;
Texture* bg2;
//and theGrid
Grid* theGrid;

/////////////////////////////////////////////////
///Declare our font
/////////////////////////////////////////////////
freetype::font_data scoreFont;
/////////////////////////////////////////////////////////
//Initialize the variables
///////////////////////////////////////////////////////
typedef dStructs::point point;
const int XSize = 755, YSize = 600;point offset = {333,145};
point mousePos = {0,0};void init(void)
{
//printf("\n......Hello Guy. \n....\nInitilising");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,XSize,0,YSize);

//////////////////////////
//initialise the fonts
/////////////////////////try{
scoreFont.init("Visitor TT2 BRK Regular.ttf", 20);
} catch (std::exception &e) {
MessageBox(NULL, e.what(), "EXCEPTION CAUGHT", MB_OK | MB_ICONINFORMATION);

}
///////////////////////////////////////////////////////////////
///bg new MEMORY MANAGED EDITION
//////////////////////////////////////////////////////////////////
unique_ptr<Texture> bg(new Texture(1024,1024,"BackGround.png"));
unique_ptr<Texture> bg2(new Texture(1024,1024,"BackGround2.png"));
unique_ptr<Grid> theGrid(new Grid(offset));
/////////////////////////////////////////////////
/// Old bad-memory-management style of pointed objects
/////////////////////////////////////////////////
//bg = new Texture(1024,1024,"BackGround.png");
//bg2 = new Texture(1024,1024,"BackGround2.png");
//theGrid = new Grid(offset);

glClearColor(0,0.4,0.7,1);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//activate the alpha blending functionality
glEnable(GL_BLEND);
glLineWidth(2);         // Width of the drawing line
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
//printf("\nInitialisation Complete");

}

void myPassiveMouse(int x, int y)
{
//Stupid OGL coordinate system
y = YSize - y;
mousePos.x = x;
mousePos.y = y;
printf("\nthe mouse coordinates are (%f,%f)",mousePos.x, mousePos.y);
}

void displayGameplayHUD()
{
///////////////////////////////
//SCORE
//////////////////////////////
glColor4f(0.7f,0.0f,0.0f,7.0f);//set the colour of the text
freetype::print(scoreFont, 100,400,"SCORE: ");
glColor4f(1.0f,1.0f,1.0f,1.0f);//Default texture colour. Makes text white, and all other texture's as theyre meant to be.

}

//////////////////////////////////////////////////////
void display()
{
////printf("\nBeginning Display");
glClear(GL_COLOR_BUFFER_BIT);//clear the colour buffer

glPushMatrix();
theGrid->doGridCalculations();//MODEL

point bgLoc = {XSize/2,YSize/2};
point bgSize = {XSize,YSize};
bg2->draw(bgLoc,bgSize);
theGrid->drawGrid();//DISPLAY
bg->draw(bgLoc,bgSize);

if(theGrid->gridState == Grid::STATIC)
{
theGrid->hoverOverBlocks(mousePos);//CONTROLLER
}

displayGameplayHUD();

glPopMatrix();

glFlush();  // Finish the drawing
glutSwapBuffers();
////printf("\nFresh Display Loaded");

glutPostRedisplay();
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);    // GLUT Initialization
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); // Initializing the Display mode
glutInitWindowSize(755,600);  // Define the window size
glutCreateWindow("Gem Miners");   // Create the window, with caption.
init();   // All OpenGL initialization//-- Callback functions ---------------------
glutDisplayFunc(display);
//glutKeyboardFunc(mykey);
//glutSpecialFunc(processSpecialKeys);
//glutSpecialUpFunc(processSpecialUpKeys);
glutMouseFunc(mymouse);

glutPassiveMotionFunc(myPassiveMouse);

glutMainLoop();   // Loop waiting for event
}

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

Заранее спасибо,
парень

0

Решение

Это глобальные необработанные указатели:

Texture* bg;
Texture* bg2;
//and theGrid
Grid* theGrid;

Это совершенно не связано unique_ptrs, локальный для функции init.

unique_ptr<Texture> bg(new Texture(1024,1024,"BackGround.png"));
unique_ptr<Texture> bg2(new Texture(1024,1024,"BackGround2.png"));
unique_ptr<Grid> theGrid(new Grid(offset));

Когда unique_ptrs выходят за рамки, они уничтожены. Объекты, на которые они указывают, также уничтожаются, потому что это то, что unique_ptr делает в своем деструкторе. Ни в одной точке этого процесса не было глобальных сырых указателей, связанных с разгромом. Они были спрятаны местными unique_ptrс тем же именем.

Вы должны изменить ваши глобальные сырые указатели на unique_ptrs. Затем вы можете установить их (не объявлять их повторно) в функции init следующим образом:

bg.reset(new Texture(1024,1024,"BackGround.png"));
bg2.reset(new Texture(1024,1024,"BackGround2.png"));
theGrid.reset(new Grid(offset));
3

Другие решения

Уникальные указатели, которые вы создаете в своем init Функция не изменяет указатели, объявленные в области видимости файла, значения в области видимости по умолчанию инициализируются 0 или nullptr (Я не очень хорошо разбираюсь в C ++ 11, поэтому я не уверен, какой именно).

Что вы делаете в init Функция создает три новый объекты с именами, которые тень те, которые находятся в области видимости файла, поэтому, когда вы используете их в области видимости файла, вы получаете нарушение доступа, потому что они никогда не устанавливаются, чтобы указывать на что-либо допустимое.

2

Ваш unique_ptr<Grid> в init является локальным для этой функции. unique_ptr<Grid> выйдет из области видимости в конце функции, уничтожая себя и Grid он владеет. Кажется, вы хотите иметь глобальный объект unique_ptr<Grid> theGrid; который заменяет Grid* theGrid; у вас есть момент. Затем в init ты можешь сделать:

theGrid.reset(new Grid(offset));

theGrid к которому обращаются в display это глобальный theGrid типа Grid*,

То же самое верно и для других unique_ptrВы пытались создать.

Конечно, вместо глобального объекта было бы гораздо лучше передавать эти объекты, но использование GLUT делает это немного болезненным.

2
По вопросам рекламы [email protected]