2013-02-05 26 views
0

根据我最近在面试时的建议,我被建议研究C++ 11的unique_ptr功能,作为自动垃圾收集的一种手段。因此,我使用了一个较老的项目,并用unique_ptrs替换了我的原始指针,这些指针用'new'关键字创建。不过,我想我已经到了一个所有权问题。我的新Unique_ptrs的所有权?

在我的mainclass.cpp(发布如下)请注意init函数和3个unique_ptrs到我创建的新实例化对象。命名为“bg”,“bg2”和“theGrid”。 ()注意到他们下面的声明是他们过去如何完成的,并且切换回这种方法,程序运行得很好。)

但是,使用unique_ptrs,函数void display()中的行:

theGrid->doGridCalculations();//MODEL 

生成访问冲突。这也是序列中第一次引用任何尖锐的对象,这导致我相信unique_ptr的所有权已经在某处丢失了。然而,unique_ptrs本身永远不会被传递到另一个函数或容器中,并保留在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 
} 

我认为所有权需要在某些时候被转移,但我不知道在哪里。

由于提前, 盖伊

+1

你意识到''bg'和bg2''theGrid'在'的init()'初始化该功能的本地? – juanchopanza

+0

'unique_ptr'就是垃圾回收。您仍然必须管理'unique_ptr'对象的生命周期;当对象超出范围时会自动删除,但这不是垃圾收集。 'shared_ptr'接近,但仍不相同;如果你有两个对象,每个对象都持有'shared_ptr'对象,它们将永远不会被销毁。垃圾收集器将摆脱它们。 –

回答

3

这些都是全球原始指针:

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

这些是完全无关的unique_ptr S,本地的初始化函数。

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_ptr超出范围时,它们被销毁。它们指向的对象也被销毁,因为那是unique_ptr在它的析构函数中所做的。在这个过程中,没有任何一点是与崩溃有关的全球原始指针。他们被同名的当地unique_ptr隐藏。

您应该将全局原始指针更改为unique_ptr s。然后你可以将它们设置(不重新申报他们)在初始化函数是这样的:

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

谢谢,这和以前一样工作,我现在对原始ptrs和unique_ptr功能之间的所有权和差异有了更深的理解。 –

2

unique_ptr<Grid>init是局部的功能。 unique_ptr<Grid>将在函数结束时超出范围,破坏它本身以及它拥有的Grid。看起来好像你想要实际上有一个全球对象unique_ptr<Grid> theGrid;,它取代了你在这个世界上的Grid* theGrid;。然后在init你可以这样做:

theGrid.reset(new Grid(offset)); 

是在display被访问的theGridGrid*型的全球theGrid

对于您尝试创建的其他unique_ptr完全相同。

当然,而不是一个全局对象,将这些对象传递给它会好很多,但是使用GLUT会让这有点痛苦。

2

您在init功能不会修改在文件范围内声明的指针创建的唯一指针,那些在文件范围是默认初始化为0或nullptr(我不是那么好,在C++ 11深谙所以我不确定哪个)。

你正在做的init功能是什么与阴影的那些在文件范围内,所以,当你走在文件范围内使用那些你得到一个访问冲突,因为他们的名字创建三个新对象永远不会指向任何有效的东西。