0

最近の就職面接での提案によると、自動化されたガベージ コレクションの手段として、C++11 の unique_ptr 機能を調査するように勧められました。だから私は古いプロジェクトを使用しており、「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 
}

ある時点で所有権を譲渡する必要があると思いますが、どこにあるのかわかりません。

前もってありがとう、ガイ

4

3 に答える 3

3

これらはグローバル生ポインタです。

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

これらはunique_ptrinit 関数にローカルな、まったく無関係の です。

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_ptrs に変更する必要があります。次に、次のように init 関数でそれらを設定できます (再宣言しないでください)。

bg.reset(new Texture(1024,1024,"BackGround.png"));
bg2.reset(new Texture(1024,1024,"BackGround2.png"));
theGrid.reset(new Grid(offset));
于 2013-02-05T11:45:51.163 に答える
2

あなたのunique_ptr<Grid>ininitはその関数に対してローカルです。関数のunique_ptr<Grid>終わりにはスコープから外れ、それ自体とGridそれが所有するものを破壊します。unique_ptr<Grid> theGrid;あなたは実際にあなたが瞬間に持っているものを置き換えるグローバルオブジェクトを持ちたいようですGrid* theGrid;。次に、次のinitことができます。

theGrid.reset(new Grid(offset));

theGridアクセスされているは、タイプのdisplayグローバルです。theGridGrid*

unique_ptr作成しようとした他のsについてもまったく同じことが言えます。

もちろん、グローバルオブジェクトよりも、これらのオブジェクトを渡す方がはるかに優れていますが、GLUTを使用すると少し面倒になります。

于 2013-02-05T11:40:22.250 に答える
2

関数で作成する一意のポインターinitは、ファイルスコープで宣言されたポインターを変更しません。ファイルスコープのポインターは、デフォルトで0またはnullptr(C ++ 11に精通していないため、よくわかりません)に初期化されます。どれの)。

initこの関数で行っているのは、ファイルスコープのオブジェクトをシャドウする名前の3つの新しいオブジェクトを作成することです。したがって、ファイルスコープのオブジェクトを使用しようとすると、有効なオブジェクトを指すように設定されていないため、アクセス違反が発生します。

于 2013-02-05T11:41:27.023 に答える