아래 코드에서 TEST1은 몇 번 생성될까요?


TEST1 GetTest1_1()

{

           TEST1 test1;

           test1.nValue = 11;

 

           return test1;

}

 

int main()

{

           ....

           auto test1_1 = GetTest1_1();

           ....

}

 

위의 코드를 실행하면 main에서 TEST1 객체 생성(1), GetTest1_1() 함수에서 TEST1 객체 생성(2)에 의해 TEST1은 총 2번 만들어집니다.

 

그러나 실제로는 C++ 최적화(즉 릴리즈모드로 컴파일 하면)에 의해 TEST1 객체는 한번만 생성합니다. 위의 최적화를 NRVO라고 합니다(RVO도 있습니다).

 

그런데 NRVO는 한계가 있습니다. 아래와 같은 경우에서는 NRVO 최적화를 사용할 수 없습니다.

 

TEST1 GetTest1_2( int nTemp )

{

           TEST1 test1;

           test1.nValue = 11;

 

           if( nTemp > 100 )

           {

                     test1.nValue = 111;

                     return test1;

           }

 

           return test1;

}

 

코드를 보면 알겠지만 TEST1 객체를 조건문에 의해서 다르게 반환하는 경우 컴파일러는 NRVO 최적화를 하지 않습니다.

 

이때는 C++11 move 생성자를 사용하여 최적화를 할 수 있습니다.

 

C++11에서는 GetTest1_2와 같은 상황일 때 TEST1move 생성자를 정의해 놓으면 컴파일러가 move 생성자를 사용합니다.

당연하겠지만 move 생성자를 정의하고 있어도 NRVO를 사용할 수 있으면 NRVO 최적화를 최우선적으로 사용합니다.

 

 

< 예제 코드 >

#include <iostream>

 

struct TEST1

{

           int nValue;

 

           TEST1()

           {

                     std::cout << "TEST1 생성자" << std::endl;

           }

          

           ~TEST1()

           {

                     std::cout << "TEST1 소멸자" << std::endl;

           }

 

           TEST1(const TEST1& obj)

           {

                     nValue = obj.nValue;

 

                     std::cout << "TEST1 복사 생성자" << std::endl;

           }

};

 

struct TEST2

{

           int nValue;

 

           TEST2()

           {

                     std::cout << "TEST2 생성자" << std::endl;

           }

          

           ~TEST2()

           {

                     std::cout << "TEST2 소멸자" << std::endl;

           }

 

           TEST2(const TEST2& obj)

           {

                     nValue = obj.nValue;

 

                     std::cout << "TEST2 복사 생성자" << std::endl;

           }

          

           TEST2(TEST2&& obj)

           {

                     nValue = obj.nValue;

 

                     std::cout << "TEST2 move 생성자" << std::endl;

           }

};

 

 

TEST1 GetTest1_1()

{

           TEST1 test1;

           test1.nValue = 11;

 

           return test1;

}

 

TEST1 GetTest1_2( int nTemp )

{

           TEST1 test1;

           test1.nValue = 11;

 

           if( nTemp > 100 )

           {

                     test1.nValue = 111;

                     return test1;

           }

 

           return test1;

}

 

TEST2 GetTest2_1()

{

           TEST2 test2;

           test2.nValue = 11;

 

           return test2;

}

 

TEST2 GetTest2_2( int nTemp )

{

           TEST2 test2;

           test2.nValue = 11;

 

           if( nTemp > 100 )

           {

                     test2.nValue = 111;

                     return test2;

           }

 

           return test2;

}

 

int main()

{

           std::cout << "TEST1 - NRVO 사용" << std::endl;

           {

                     auto test1_1 = GetTest1_1();

           }

 

           std::cout << std::endl;

          

           std::cout << "TEST1 - NRVO 사용 불가" << std::endl;

           {

                     auto test1_2 = GetTest1_2(101);

           }

 

           std::cout << std::endl;

           std::cout << std::endl;

          

           std::cout << "TEST2 - NRVO 사용" << std::endl;

           {

                     auto test2_1 = GetTest2_1();

           }

 

           std::cout << std::endl;

          

           std::cout << "TEST2 - move 생성자 사용" << std::endl;

           {

                     auto test2_2 = GetTest2_2(101);

           }

 

          

           return 0;

}

 

< 결과 >


저작자 표시
신고
by 흥배 2012.10.24 09:30
| 1 |