/*

 * Copyright 1993-2012 NVIDIA Corporation.  All rights reserved.

 *

 * Please refer to the NVIDIA end user license agreement (EULA) associated

 * with this source code for terms and conditions that govern your use of

 * this software. Any use, reproduction, disclosure, or distribution of

 * this software and related documentation outside the terms of the EULA

 * is strictly prohibited.

 *

 */


/*

    Volume rendering sample


    This sample loads a 3D volume from disk and displays it using

    ray marching and 3D textures.


    Note - this is intended to be an example of using 3D textures

    in CUDA, not an optimized volume renderer.


    Changes

    sgg 22/3/2010

    - updated to use texture for display instead of glDrawPixels.

    - changed to render from front-to-back rather than back-to-front.

*/


/*

// OpenGL Graphics includes

#include <GL/glew.h>

#if defined (__APPLE__) || defined(MACOSX)

#include <GLUT/glut.h>

#else

#include <GL/freeglut.h>

#endif


// CUDA Runtime, Interop, and includes

#include <cuda_runtime.h>

#include <cuda_gl_interop.h>

#include <vector_types.h>

#include <vector_functions.h>

#include <driver_functions.h>


// CUDA utilities

#include <helper_cuda.h>

#include <helper_cuda_gl.h>


// Helper functions

#include <helper_cuda.h>

#include <helper_functions.h>

#include <helper_timer.h>


typedef unsigned int uint;

typedef unsigned char uchar;


#define MAX_EPSILON_ERROR 5.00f

#define THRESHOLD         0.30f


// Define the files that are to be save and the reference images for validation

const char *sOriginal[] =

{

    "volume.ppm",

    NULL

};


const char *sReference[] =

{

    "ref_volume.ppm",

    NULL

};


const char *sSDKsample = "CUDA 3D Volume Render";


const char *volumeFilename = "Bucky.raw";

cudaExtent volumeSize = make_cudaExtent(32, 32, 32);

typedef unsigned char VolumeType;


//char *volumeFilename = "mrt16_angio.raw";

//cudaExtent volumeSize = make_cudaExtent(416, 512, 112);

//typedef unsigned short VolumeType;


uint width = 512, height = 512;

dim3 blockSize(16, 16);

dim3 gridSize;


float3 viewRotation;

float3 viewTranslation = make_float3(0.0, 0.0, -4.0f);

float invViewMatrix[12];


float density = 0.05f;

float brightness = 1.0f;

float transferOffset = 0.0f;

float transferScale = 1.0f;

bool linearFiltering = true;


GLuint pbo = 0;     // OpenGL pixel buffer object

GLuint tex = 0;     // OpenGL texture object

struct cudaGraphicsResource *cuda_pbo_resource; // CUDA Graphics Resource (to transfer PBO)


StopWatchInterface *timer = 0;


// Auto-Verification Code

const int frameCheckNumber = 2;

int fpsCount = 0;        // FPS count for averaging

int fpsLimit = 1;        // FPS limit for sampling

int g_Index = 0;

unsigned int frameCount = 0;


int *pArgc;

char **pArgv;


#ifndef MAX

#define MAX(a,b) ((a > b) ? a : b)

#endif


extern "C" void setTextureFilterMode(bool bLinearFilter);

extern "C" void initCuda(void *h_volume, cudaExtent volumeSize);

extern "C" void freeCudaBuffers();

extern "C" void render_kernel(dim3 gridSize, dim3 blockSize, uint *d_output, uint imageW, uint imageH,

                              float density, float brightness, float transferOffset, float transferScale);

extern "C" void copyInvViewMatrix(float *invViewMatrix, size_t sizeofMatrix);


void initPixelBuffer();


void computeFPS()

{

    frameCount++;

    fpsCount++;


    if (fpsCount == fpsLimit)

    {

        char fps[256];

        float ifps = 1.f / (sdkGetAverageTimerValue(&timer) / 1000.f);

        sprintf(fps, "Volume Render: %3.1f fps", ifps);


        glutSetWindowTitle(fps);

        fpsCount = 0;


        fpsLimit = (int)MAX(1.f, ifps);

        sdkResetTimer(&timer);

    }

}


// render image using CUDA

void render()

{

    copyInvViewMatrix(invViewMatrix, sizeof(float4)*3);


    // map PBO to get CUDA device pointer

    uint *d_output;

    // map PBO to get CUDA device pointer

    checkCudaErrors(cudaGraphicsMapResources(1, &cuda_pbo_resource, 0));

    size_t num_bytes;

    checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&d_output, &num_bytes,

                                                         cuda_pbo_resource));

    //printf("CUDA mapped PBO: May access %ld bytes\n", num_bytes);


    // clear image

    checkCudaErrors(cudaMemset(d_output, 0, width*height*4));


    // call CUDA kernel, writing results to PBO

    render_kernel(gridSize, blockSize, d_output, width, height, density, brightness, transferOffset, transferScale);


    getLastCudaError("kernel failed");


    checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0));

}


// display results using OpenGL (called by GLUT)

void display()

{

    sdkStartTimer(&timer);


    // use OpenGL to build view matrix

    GLfloat modelView[16];

    glMatrixMode(GL_MODELVIEW);

    glPushMatrix();

    glLoadIdentity();

    glRotatef(-viewRotation.x, 1.0, 0.0, 0.0);

    glRotatef(-viewRotation.y, 0.0, 1.0, 0.0);

    glTranslatef(-viewTranslation.x, -viewTranslation.y, -viewTranslation.z);

    glGetFloatv(GL_MODELVIEW_MATRIX, modelView);

    glPopMatrix();


    invViewMatrix[0] = modelView[0];

    invViewMatrix[1] = modelView[4];

    invViewMatrix[2] = modelView[8];

    invViewMatrix[3] = modelView[12];

    invViewMatrix[4] = modelView[1];

    invViewMatrix[5] = modelView[5];

    invViewMatrix[6] = modelView[9];

    invViewMatrix[7] = modelView[13];

    invViewMatrix[8] = modelView[2];

    invViewMatrix[9] = modelView[6];

    invViewMatrix[10] = modelView[10];

    invViewMatrix[11] = modelView[14];


    render();


    // display results

    glClear(GL_COLOR_BUFFER_BIT);


    // draw image from PBO

    glDisable(GL_DEPTH_TEST);


    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

#if 0

    // draw using glDrawPixels (slower)

    glRasterPos2i(0, 0);

    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);

    glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);

    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);

#else

    // draw using texture


    // copy from pbo to texture

    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);

    glBindTexture(GL_TEXTURE_2D, tex);

    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);

    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);


    // draw textured quad

    glEnable(GL_TEXTURE_2D);

    glBegin(GL_QUADS);

glTexCoord2f(0, 0);

glVertex2f(0, 0);

glTexCoord2f(1, 0);

glVertex2f(1, 0);

glTexCoord2f(1, 1);

glVertex2f(1, 1);

glTexCoord2f(0, 1);

glVertex2f(0, 1);

    glEnd();


    glDisable(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, 0);

#endif


    glutSwapBuffers();

    glutReportErrors();


    sdkStopTimer(&timer);


    computeFPS();

}


void idle()

{

    glutPostRedisplay();

}


void keyboard(unsigned char key, int x, int y)

{

    switch (key)

    {

        case 27:

            exit(EXIT_SUCCESS);

            break;


        case 'f':

            linearFiltering = !linearFiltering;

            setTextureFilterMode(linearFiltering);

            break;


        case '+':

            density += 0.01f;

            break;


        case '-':

            density -= 0.01f;

            break;


        case ']':

            brightness += 0.1f;

            break;


        case '[':

            brightness -= 0.1f;

            break;


        case ';':

            transferOffset += 0.01f;

            break;


        case '\'':

            transferOffset -= 0.01f;

            break;


        case '.':

            transferScale += 0.01f;

            break;


        case ',':

            transferScale -= 0.01f;

            break;


        default:

            break;

    }


    printf("density = %.2f, brightness = %.2f, transferOffset = %.2f, transferScale = %.2f\n", density, brightness, transferOffset, transferScale);

    glutPostRedisplay();

}


int ox, oy;

int buttonState = 0;


void mouse(int button, int state, int x, int y)

{

    if (state == GLUT_DOWN)

    {

        buttonState  |= 1<<button;

    }

    else if (state == GLUT_UP)

    {

        buttonState = 0;

    }


    ox = x;

    oy = y;

    glutPostRedisplay();

}


void motion(int x, int y)

{

    float dx, dy;

    dx = (float)(x - ox);

    dy = (float)(y - oy);


    if (buttonState == 4)

    {

        // right = zoom

        viewTranslation.z += dy / 100.0f;

    }

    else if (buttonState == 2)

    {

        // middle = translate

        viewTranslation.x += dx / 100.0f;

        viewTranslation.y -= dy / 100.0f;

    }

    else if (buttonState == 1)

    {

        // left = rotate

        viewRotation.x += dy / 5.0f;

        viewRotation.y += dx / 5.0f;

    }


    ox = x;

    oy = y;

    glutPostRedisplay();

}


int iDivUp(int a, int b)

{

    return (a % b != 0) ? (a / b + 1) : (a / b);

}


void reshape(int w, int h)

{

    width = w;

    height = h;

    initPixelBuffer();


    // calculate new grid size

    gridSize = dim3(iDivUp(width, blockSize.x), iDivUp(height, blockSize.y));


    glViewport(0, 0, w, h);


    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();


    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);

}


void cleanup()

{

    sdkDeleteTimer(&timer);


    freeCudaBuffers();


    if (pbo)

    {

        cudaGraphicsUnregisterResource(cuda_pbo_resource);

        glDeleteBuffersARB(1, &pbo);

        glDeleteTextures(1, &tex);

    }

}


void initGL(int *argc, char **argv)

{

    // initialize GLUT callback functions

    glutInit(argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);

    glutInitWindowSize(width, height);

    glutCreateWindow("CUDA volume rendering");


    glewInit();


    if (!glewIsSupported("GL_VERSION_2_0 GL_ARB_pixel_buffer_object"))

    {

        printf("Required OpenGL extensions missing.");

        exit(EXIT_SUCCESS);

    }

}


void initPixelBuffer()

{

    if (pbo)

    {

        // unregister this buffer object from CUDA C

        checkCudaErrors(cudaGraphicsUnregisterResource(cuda_pbo_resource));


        // delete old buffer

        glDeleteBuffersARB(1, &pbo);

        glDeleteTextures(1, &tex);

    }


    // create pixel buffer object for display

    glGenBuffersARB(1, &pbo);

    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);

    glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, width*height*sizeof(GLubyte)*4, 0, GL_STREAM_DRAW_ARB);

    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);


    // register this buffer object with CUDA

    checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_pbo_resource, pbo, cudaGraphicsMapFlagsWriteDiscard));


    // create texture for display

    glGenTextures(1, &tex);

    glBindTexture(GL_TEXTURE_2D, tex);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glBindTexture(GL_TEXTURE_2D, 0);

}


// Load raw data from disk

void *loadRawFile(char *filename, size_t size)

{

    FILE *fp = fopen(filename, "rb");


    if (!fp)

    {

        fprintf(stderr, "Error opening file '%s'\n", filename);

        return 0;

    }


    void *data = malloc(size);

    size_t read = fread(data, 1, size, fp);

    fclose(fp);


    printf("Read '%s', %d bytes\n", filename, read);


    return data;

}


// General initialization call for CUDA Device

int chooseCudaDevice(int argc, const char **argv, bool bUseOpenGL)

{

    int result = 0;


    if (bUseOpenGL)

    {

        result = findCudaGLDevice(argc, argv);

    }

    else

    {

        result = findCudaDevice(argc, argv);

    }


    return result;

}


void runSingleTest(const char *ref_file, const char *exec_path)

{

    bool bTestResult = true;


    uint *d_output;

    checkCudaErrors(cudaMalloc((void **)&d_output, width*height*sizeof(uint)));

    checkCudaErrors(cudaMemset(d_output, 0, width*height*sizeof(uint)));


    float modelView[16] =

    {

        1.0f, 0.0f, 0.0f, 0.0f,

        0.0f, 1.0f, 0.0f, 0.0f,

        0.0f, 0.0f, 1.0f, 0.0f,

        0.0f, 0.0f, 4.0f, 1.0f

    };


    invViewMatrix[0] = modelView[0];

    invViewMatrix[1] = modelView[4];

    invViewMatrix[2] = modelView[8];

    invViewMatrix[3] = modelView[12];

    invViewMatrix[4] = modelView[1];

    invViewMatrix[5] = modelView[5];

    invViewMatrix[6] = modelView[9];

    invViewMatrix[7] = modelView[13];

    invViewMatrix[8] = modelView[2];

    invViewMatrix[9] = modelView[6];

    invViewMatrix[10] = modelView[10];

    invViewMatrix[11] = modelView[14];


    // call CUDA kernel, writing results to PBO

    copyInvViewMatrix(invViewMatrix, sizeof(float4)*3);


    // Start timer 0 and process n loops on the GPU

    int nIter = 10;


    for (int i = -1; i < nIter; i++)

    {

        if (i == 0)

        {

            cudaDeviceSynchronize();

            sdkStartTimer(&timer);

        }


        render_kernel(gridSize, blockSize, d_output, width, height, density, brightness, transferOffset, transferScale);

    }


    cudaDeviceSynchronize();

    sdkStopTimer(&timer);

    // Get elapsed time and throughput, then log to sample and master logs

    double dAvgTime = sdkGetTimerValue(&timer)/(nIter * 1000.0);

    printf("volumeRender, Throughput = %.4f MTexels/s, Time = %.5f s, Size = %u Texels, NumDevsUsed = %u, Workgroup = %u\n",

           (1.0e-6 * width * height)/dAvgTime, dAvgTime, (width * height), 1, blockSize.x * blockSize.y);



    getLastCudaError("Error: render_kernel() execution FAILED");

    checkCudaErrors(cudaDeviceSynchronize());


    unsigned char *h_output = (unsigned char *)malloc(width*height*4);

    checkCudaErrors(cudaMemcpy(h_output, d_output, width*height*4, cudaMemcpyDeviceToHost));


    sdkSavePPM4ub("volume.ppm", h_output, width, height);

    bTestResult = sdkComparePPM("volume.ppm", sdkFindFilePath(ref_file, exec_path), MAX_EPSILON_ERROR, THRESHOLD, true);


    cudaFree(d_output);

    free(h_output);

    cleanup();


    exit(bTestResult ? EXIT_SUCCESS : EXIT_FAILURE);

}


////////////////////////////////////////////////////////////////////////////////

// Program main

////////////////////////////////////////////////////////////////////////////////

int

main(int argc, char **argv)

{

    pArgc = &argc;

    pArgv = argv;


    char *ref_file = NULL;


    //start logs

    printf("%s Starting...\n\n", sSDKsample);


    if (checkCmdLineFlag(argc, (const char **)argv, "file"))

    {

        getCmdLineArgumentString(argc, (const char **)argv, "file", &ref_file);

        fpsLimit = frameCheckNumber;

    }


    if (ref_file)

    {

        // use command-line specified CUDA device, otherwise use device with highest Gflops/s

        chooseCudaDevice(argc, (const char **)argv, false);

    }

    else

    {

        // First initialize OpenGL context, so we can properly set the GL for CUDA.

        // This is necessary in order to achieve optimal performance with OpenGL/CUDA interop.

        initGL(&argc, argv);


        // use command-line specified CUDA device, otherwise use device with highest Gflops/s

        chooseCudaDevice(argc, (const char **)argv, true);

    }


    // parse arguments

    char *filename;


    if (getCmdLineArgumentString(argc, (const char **) argv, "volume", &filename))

    {

        volumeFilename = filename;

    }


    int n;


    if (checkCmdLineFlag(argc, (const char **) argv, "size"))

    {

        n = getCmdLineArgumentInt(argc, (const char **) argv, "size");

        volumeSize.width = volumeSize.height = volumeSize.depth = n;

    }


    if (checkCmdLineFlag(argc, (const char **) argv, "xsize"))

    {

        n = getCmdLineArgumentInt(argc, (const char **) argv, "xsize");

        volumeSize.width = n;

    }


    if (checkCmdLineFlag(argc, (const char **) argv, "ysize"))

    {

        n = getCmdLineArgumentInt(argc, (const char **) argv, "ysize");

        volumeSize.height = n;

    }


    if (checkCmdLineFlag(argc, (const char **) argv, "zsize"))

    {

        n= getCmdLineArgumentInt(argc, (const char **) argv, "zsize");

        volumeSize.depth = n;

    }


    // load volume data

    char *path = sdkFindFilePath(volumeFilename, argv[0]);


    if (path == 0)

    {

        printf("Error finding file '%s'\n", volumeFilename);

        exit(EXIT_FAILURE);

    }


    size_t size = volumeSize.width*volumeSize.height*volumeSize.depth*sizeof(VolumeType);

    void *h_volume = loadRawFile(path, size);


    initCuda(h_volume, volumeSize);

    free(h_volume);


    sdkCreateTimer(&timer);


    printf("Press '+' and '-' to change density (0.01 increments)\n"

           "      ']' and '[' to change brightness\n"

           "      ';' and ''' to modify transfer function offset\n"

           "      '.' and ',' to modify transfer function scale\n\n");


    // calculate new grid size

    gridSize = dim3(iDivUp(width, blockSize.x), iDivUp(height, blockSize.y));


    if (ref_file)

    {

        runSingleTest(ref_file, argv[0]);

    }

    else

    {

        // This is the normal rendering path for VolumeRender

        glutDisplayFunc(display);

        glutKeyboardFunc(keyboard);

        glutMouseFunc(mouse);

        glutMotionFunc(motion);

        glutReshapeFunc(reshape);

        glutIdleFunc(idle);


        initPixelBuffer();


        atexit(cleanup);


        glutMainLoop();

    }


    cudaDeviceReset();

    exit(EXIT_SUCCESS);

}


*/

/*

#include <stdio.h>

#include <stdlib.h>

#include <omp.h>

#include <boost/timer.hpp>



int num_steps=500000000; 




#define OPENMP

int main()

{

int i;

double x, step, sum = 0.0;

step = 1.0/(double) num_steps;


boost::timer t;


#ifdef NOOPENMP

for (i=0; i<num_steps; i++) 

{

x = (i+0.5) * step;

sum += 4.0/(1.0 + x*x);

}

#endif


#ifdef OPENMP


#pragma omp parallel for

for (i=0; i<num_steps; i++) 

{

x = (i+0.5) * step;

sum += 4.0/(1.0 + x*x);

}

#endif


#ifdef OPENMP_RE

#pragma omp parallel for private(x) reduction(+:sum)

for (i=0; i<num_steps; i++) 

{

x = (i+0.5) * step;

sum += 4.0/(1.0 + x*x);

}

#endif


double t2_insert = t.elapsed();

printf("time:  %.8lf \n", t2_insert);

printf("PI = %.8f (sum = %.8f)\n", step*sum, sum);


return EXIT_SUCCESS;

}

*/


'OpenMP,PPL' 카테고리의 다른 글

FOR_reduction.cpp  (0) 2014.08.27
FOR_default.cpp  (0) 2014.08.27
CRITICAL_SECTION.cpp  (0) 2014.08.27

/*

#include <stdio.h>

#include <stdlib.h>

#include <omp.h>

#include <boost/timer.hpp>



const int num_steps=100; 



int main()

{

boost::timer t;



int sum = 0, i = 0;

int Data[num_steps] = {0};


for(i =0 ; i < num_steps; i++)

{

Data[i] = i + 1;

}

#pragma  omp parallel for reduction(+:sum)

for(i = 0 ; i < num_steps; i++)

{

sum += Data[i];

}


printf(" 총합 sum = %d \n", sum);



double t2_insert = t.elapsed();

printf("time:  %.8lf \n", t2_insert);


return EXIT_SUCCESS;

}

*/

'OpenMP,PPL' 카테고리의 다른 글

OP_TEST_REDUCTION.cpp  (0) 2014.08.27
FOR_default.cpp  (0) 2014.08.27
CRITICAL_SECTION.cpp  (0) 2014.08.27


/*

#include <stdio.h>

#include <stdlib.h>

#include <omp.h>

#include <boost/timer.hpp>



int num_steps=100; 



int main()

{

boost::timer t;


int a = 0;

printf("main area / a = %d  \n",  a);

#pragma  omp parallel default(none)  private(a) // default(shared) 

{

if( omp_get_thread_num() == 0) 

a = 1;

else 

a = 2;


printf("%d thread area / a = %d  \n", omp_get_thread_num(), a);

}


    printf("main area / a = %d  \n",  a);

double t2_insert = t.elapsed();

printf("time:  %.8lf \n", t2_insert);

return EXIT_SUCCESS;

}


*/

'OpenMP,PPL' 카테고리의 다른 글

OP_TEST_REDUCTION.cpp  (0) 2014.08.27
FOR_reduction.cpp  (0) 2014.08.27
CRITICAL_SECTION.cpp  (0) 2014.08.27

/*

#include <stdio.h>

#include <stdlib.h>

#include <omp.h>

#include <boost/timer.hpp>



const int num_steps=1000; 



int main()

{

boost::timer t;



int sum = 0, i = 0;


float * Data = new float[num_steps];


for(i =0 ; i < num_steps; i++)

{

Data[i] = i;

}

float max = 0;

#pragma  omp parallel for 

for(i = 0 ; i < num_steps; i++)

{

#pragma  omp critical (MAXVALUE)

{

if(max < Data[i])

max = Data[i];

}

}


printf("  max = %f \n", max);



double t2_insert = t.elapsed();

printf("time:  %.8lf \n", t2_insert);


return EXIT_SUCCESS;

}


*/

'OpenMP,PPL' 카테고리의 다른 글

OP_TEST_REDUCTION.cpp  (0) 2014.08.27
FOR_reduction.cpp  (0) 2014.08.27
FOR_default.cpp  (0) 2014.08.27


산에 오를때는 항상 똑같습니다.

얼굴을 땅에 대고 한발씩 힘들게 걷다보면 보이는것은.. 돌맹이 , 낙화 ,  흙... 

하지만  꾸준히 걸어서 마침내 꼭대기에 도착하면  

내가 오른 산이 왜 이런 이름을 갖게됬는지 알게되지요..

월악산, 계룡산, 지리산..







'주인장' 카테고리의 다른 글

세방낙조  (0) 2017.06.26
2016년 여름 그리고 94년 여름의 추억  (0) 2016.08.22
안산 바위들  (0) 2016.05.06
기분전환에 좋은 백색소음 사이트  (0) 2015.11.19
최고의 떡볶이 맛집 - 영천시장 떡볶이 -  (0) 2015.11.09

C++ 경우는 정의되지 않은 행동을 합니다. (제작자에 따라서 다름) 따라서 항상 검사를 미리하고 사용해야합니다.

 

// queue::empty

#include <iostream>       // std::cout
#include <queue>          // std::queue

int main ()
{
  std::queue<string> myqueue;
  myqueue.front();  // <--------------- what happen ? 
 
  return 0; 

} 

 

  P.S

 

  제가 처음 프로그래밍 배울때 만든 큐는 리턴값이 bool  형이고  매개변수를 통해서 값을 반환하였습니다.

  자바의 경우는 null 객체를 반환합니다.

  Scala 언어의 경우는 예외를 반환합니다.

 

  무엇이 좋은지는 각자 판단을 ~!



안전한 C++ 라이프를 위한 스마트포인터에 대해 정리를 해봤습니다. (2012년 현재) 

마지막 한줌의 속도라도 짜내야하는 그런 부분 제외하고는 웬만하면 C++ 말고 다른것을 사용하라고 조언드리고 싶고, Rust 의 빠른 발전을 기대합니다.  



1. Scoped_ptr (boost)

0. 복사불가 단일 소유자
1. 
한마디로 scoped_ptr  복사할  없는 auto_ptr 이다
2. 
 가볍습니다.
3. 
제한적이다. ( 함수 내에서만 동적할당해서 쓰다가 함수를 끝낼 때는 삭제해야 하는 임시 객체를 처리할 때도 유용하게 쓰일  있습니다)
4. 
 스마트포인터를 포함하고있는 클래스도 복사불가입니다.
5. "
자원 획득은 초기화 이다." 만을 위해 존재한다레퍼런스 카운팅이 없고소유권공유,이전문제도 없다.
6. 
명확한 쓰임새를 위해서 비전에서 이것으로 교체하는게 좋을듯합니다.
7. STL 
컬렉션과 함께 사용불가


2. Scoped_array (boost)

0. 동적으로 할당한 배열에 대해 사용
1. 
복사불가 단일 소유자
2. 
동적인 배열이 필요하다면 std::vector라는 훌륭한 대체 수단이 이미 존재하는 관계로
 scoped_array 사용 목적은 주로 오래되고 복잡한 코드를 유지 보수하면서 혹시나 delete[] 잊을 수도 있는 후임자를 위해 사용해라가 되겠습니다.


3. auto_ptr (C++98)

0. 복사가능 단일 소유자
1. 
한마디로 복사할수있는 Scoped_ptr 입니다.
2. A->B 
 복사하고나서 A  소멸되면 B 스마트포인터는 빈곳을 가르킨다면 대략 낭패입니다.
3. 2
 문제를 해결하고자 auto_ptr에서는 소유권을 이전시켜버립니다. A  복사하는순간 쓸모없어지는것이지요.
4. 
레퍼런스카운팅을 하지 않는다. (단지 소유권 이전으로 단일 소유자만 존재)
5. STL 
컬렉션과 함께 사용불가


4. shared_ptr (C++TR)

: 0. 복사가능 공유소유자
: 1. 
레퍼런스 카운팅을 통해 공유를한다가장 마지막 소유자가 제거될때까지 힙에 존재합니다.
: 2. STL 
컬렉션과 함께 사용가능
: 3. 
가장 무겁다.
: 4. Copy on write 
 아니다한쪽에서 값이 바뀌면  모든 소유자가  바뀜.


5. weak_ptr (boost)

: 0.weak_ptr  share_ptr  초기화 되어야 한다는 제약.( 이것은 share_ptr 관련되어서만 사용해야함.)
: 1.weak_ptr
 객체의 생명주기에 영향을 주지 않는다. (레퍼런스 카운팅에 영향을 안준다는뜻)
: 2.enable_shared_from_this<>
 내부적으로 weak_ptr 이용하여 this 포인터의 shared_ptr 전달 문제를 해결하고 있다.
: 3.
보통 shared_ptr  circular reference 문제를 해결하기위해 사용된다.

6. unique_ptr (C++11)

: 0. auto_ptr shared_ptr 사이의 절충안
: 1. unique_ptr
 기본적으로 auto_ptr 유사하게 소유권의 이전에 기반한 동작을 한다
: 2. 
그러나 일반 복사 생성대입 연산이 아닌 C++11에서 새롭게 추가된 R-value reference 이용한다는 것이다.
: 3. C++11
에서 STL 컨테이너에서도 효율성을 위해 내부적인 복사  대입 동작은 전부 R-value reference 이용하도록 바뀌었는데
일반 복사  대입 연산자를 막아 버리는 대신 R-value reference 이용한 복사  대입 연산자만 정의한다면 STL에서도 사용할  있는 auto_ptr 생긴다는 것이 unique_ptr 의미이다.
: 4. STL 
컨테이너에서도 사용할  있다.
: 5. raw pointer
 비해 추가적인 오버헤드도 없는 스마트 포인터라   있다의미적인 뚜렷함과 안전한 사용을 위해 대부분의 암시적인 변환이 막혀 있고일반적인 대입  복사가 막혀있으므로 
unique_ptr 
끼리의 대입에는 std::move 함수를 명시적으로 사용해야 하는  코딩량이 다소 늘어난다는 불편함이 있으나안전하고 속도개선의 코딩을 위해서라면  정도는 충분히 감수할  하다.

'C++ (비공개)' 카테고리의 다른 글

C API 와 C++(STL) 호환에 관한 팁  (0) 2019.03.24
C++ 50 계명 - 이것만은 기억하자.  (1) 2019.03.19

+ Recent posts