2013-02-05 25 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功能是什麼與陰影的那些在文件範圍內,所以,當你走在文件範圍內使用那些你得到一個訪問衝突,因爲他們的名字創建三個新對象永遠不會指向任何有效的東西。