맴버 초기화 리스트

| C++
2021. 3. 23. 22:07

얼마전 새로운 사실을 알게된것 같다.

Effective C++ 에서 봤던대로 초기화는 초기화 리스트에서 진행해야한다. 그렇게 봤기 떄문이다.

그렇기에 최대한 모든 맴버 변수를 초기화 리스트에 넣었다. 하지만 의문이 든것도 사실이다.

맴버 변수가 객체로 이루어져있으면 초기화 리스트에서 진행하는게 맞아보였다 .하지만 기본 자료형은 어떨까?

 

단순 자료형만 있고 이것을 그냥 0으로 초기화하는것인데 이게 차이가 있을까 하는것이였다. 물론 객체가 존재하면 얘기는 다르겠지만 단순 자료형만으로 이루어진 클래스일때는 어떨까 하는 것이였다.

 

그러던중 어셈블리로 코드를 볼 기회가 생겼고 그것에서 기본 자료형만 있을때는 차이가 없다는 결과가 나왔다.

 

class A
{
    public:
        A():m_Num(0),
        m_double(0.0)
        {}

   private:
        int m_Num;
        double m_double;
};

class B
{
    public:
        B()
        {
            m_Num = 0;
            m_double = 0.0;
        }
   private:
        int m_Num;
        double m_double;
};

코드는 위와 같이 구성을 했고 해당 부분을 어셈블리로 보면

 

this$ = 8
A::A(void) PROC                                  ; A::A, COMDAT
        mov     QWORD PTR [rsp+8], rcx
        mov     rax, QWORD PTR this$[rsp]
        mov     DWORD PTR [rax], 0
        mov     rax, QWORD PTR this$[rsp]
        xorps   xmm0, xmm0
        movsd   QWORD PTR [rax+8], xmm0
        mov     rax, QWORD PTR this$[rsp]
        ret     0
A::A(void) ENDP                                  ; A::A

this$ = 8
B::B(void) PROC                                  ; B::B, COMDAT
        mov     QWORD PTR [rsp+8], rcx
        mov     rax, QWORD PTR this$[rsp]
        mov     DWORD PTR [rax], 0
        mov     rax, QWORD PTR this$[rsp]
        xorps   xmm0, xmm0
        movsd   QWORD PTR [rax+8], xmm0
        mov     rax, QWORD PTR this$[rsp]
        ret     0
B::B(void) ENDP                                  ; B::B

 

위처럼 결과값이 같은것으로 나왔다. 혹시나 해서 객체로도 테스트를 해보았지만 결과는 초기화 리스트를 써야한다는 것이였다.

 

이걸로 결과가 차이가 없다는걸 확인하긴 하였지만 그래도 두가지 방식을 사용하면 햇갈릴수 있으므로 초기화 리스트를 쓰는게 나은 선택일 것이다.

'C++' 카테고리의 다른 글

람다함수를 이용한 Vector 탐색 소스  (0) 2016.02.19
xmllite 설정하기  (0) 2013.08.15
:

std::pair 는 하나의 변수에 두개의 데이터 타입을 저장할떄 사용한다. 

기본적인 형식은 아래와 같다.

 

std::pair<타입1, 타입2> 변수명{타입 1 값, 타입2 값};

 

하지만 변수 선언으로만 사용하기엔 뭔가 부족해 보인다. 그렇다면 어떤게 좋을까? 예전에 값을 리턴할때 두가지 형식을 한번에 리턴하면 좋겠다는 생각이 든 적이 있다. 

 

현재 함수가 올바르게 동작된지 확인가능한 boolean  과 함수의 결과값을 동시에 ..

 

다른 방식으로도 가능한 방법은 많다 하지만 그때는 이 방식이 있으면 좋지 않을까 생각했고 그방식을 std::pair로 구현할 수 있다.

 

//answer, Errorcode
std::pair<int, int> TestDivide(int a, int b)
{
	if(b == 0)
    		return std::make_pair<int, int>(a/ b, -1);
	return std::make_pair<int, int>(a / b, 0);
}

int main()
{
	auto pair_test = TestDivide(5, 2);
    
    
    //호출 형식
    std::cout << pair_test.first << std::endl;
    std::cout << pair_test.second << std::endl;
}

std::tuple은  std::pair와 비슷하지만 여러개의 인자를 설정할수 있고 변수로도 선언 할수 있고 그것을 리턴 받는 식으로 사용할수 있다. 

std::tuple<int, int, int> get_content()
{
	return std::make_tuple(0, 0, 1);
}

하지만 받는 형식은 여러가지가 있다.

 

int main(
	auto auto_tuple = get_content();

	std::cout << std::get<0>(auto_tuple) << std::endl;
	std::cout << std::get<1>(auto_tuple) << std::endl;
	std::cout << std::get<2>(auto_tuple) << std::endl;

	int nInt1, nInt2, nInt3;

	std::tie(nInt1, nInt2, nInt3) = get_content();

	//C++17
	auto [nNum1, nNum2, nNum3] = get_content();
   
   return 0;
    
  }

모든 방식이 되지만 개인적으로 실전에서 사용은 안해서 뭐가 좋을지는 아직 모르겠다.

'C++ > C++11' 카테고리의 다른 글

C++ 11 특징 ( R Value)  (0) 2021.03.09
C++11 특징 (Uniform 초기화)  (0) 2021.03.05
C++11 특징 (lambda)  (0) 2021.03.03
C++11 특징( ranged for loop)  (0) 2021.03.03
C++11 특징 (auto)  (0) 2021.03.02
:

C++11 의 알기 쉬운 키워드로 auto  가 있다. 하지만 C++11에서는 데이터를 선언할때만 auto를 쓸수 있고 함수반환값에서는 사용이 안되었다. 

 

하지만 C++14로 오면서 이부분이 해결되었다.

 

int TestNum()			//C++11
{
	return 10;
}

auto TestNumAuto()		//C++14
{
	return 10;
}

위와같이 return 타입을 auto로 하여도 컴파일러가 데이터 타입을 유추하여 타입을 지정한다.

 

하지만 몇가지 오류는 조심해야한다.

 

auto TestErr(int nNum)		// return 타입이 int 타입과 double 타입이 존재하여 오류
{
	if(nNum > 10)
    	return 0;
	return 0.0;
}


auto Recursion(int nNum)	//재귀 함수 호출시 첫 return 에서 데이터 형식을 유추 할수없어 오류
{
	if(nNum > 10)
    	return Recursion(nNum - 1);
    return nNum;    
}

 

 

decltype는 주어진 변수의 타입을 알려주는 키워드로 기본적인 구조는 다음과 같다.

	auto a = 100;		
	auto* b = &a;
	auto k = 100;

	decltype(a) c = 50;		//변수 a의 타입인 int
	decltype(b) d = &k;		//변수 b의 타입인 int*

 

 

해당 키워드는 auto로 return 되어 데이터 형식의 구분이 어려울때 사용하면 유용하게 쓸수 있을꺼 같다.

 

:

C++ 11 특징 ( R Value)

2021. 3. 9. 01:19

이부분은 좀처럼 이해가 가질 않아서 여러 문서들을 확인을 하였다. 단순히 R Value 쓰면 좋아요 라는데 왜? 라는 이유가 계속 붙었다.  하지만 이해를 하고 나니 엄청 중요한 내용이라는 생각이 들었다. 

 

무엇보다 이해를 어렵게 한건 선행으로 알아야하는게 다른거에 비해 양이 좀 된다. 

 

먼저 변수 형식은 L Value와 R Value가 있다.  

 

L Value는 수정이 되는 데이터 R Value는 수정이 안되는 데이터 말그대로 임시 데이터이다.

 

int a = 10;


a : L Value -> 수정될수 있다. ex) a = 5;
10 : R Value -> 수정이 안된다 ex ) 10 =5 ??? error

 

다음으로 알아야할건 std::move 인데 쉽게 말하면

 

L Value 데이터 => R Value 데이터 

 

로 변환해주는 함수다. 그리고 std::move 로 넘겨진 데이터는 단순 넘기는것이 아닌 소유권까지 넘기며 기존 L Value엔 빈값이 담기게된다. (const 쓰면 그냥 복사함)

 

이정도의 정보를 가지고 아래를 보자.

 

C++에서의 함수 호출 방식은 크게 두가지였다. 

Call by Value

Call by Reference

 

Call by Value는 데이터의 복사가 이루어 지기 때문에 int 타입이나 단순한 데이터는 모르겠지만 큰 Object  파일 같은 경우 복사가 이루어지면 퍼포먼스가 크게 떨어지게 된다.

 

Call by Reference는 데이터를 참조 하기 떄문에 이런 복사에서 자유로워진다. 하지만 수정을 할수 있기에 수정을 못하도록 const를 붙여서 쓰는것이 권장이 된다.

 

하지만 두개 다 하나의 문제점이 있는데 아래의 함수를 보자

void Test1(std::string str)			// 복사를 한다.
{
	std::string strV = str;			// 복사를 한다.
}

void Test2(const std::stringt& str)	// 복사가 이루어 지지 않는다.
{
	std::string strRef = str;			// 복사를 한다.
}

int main()
{
	std::string tmp = "Test";
    
    Test1(tmp);
    Test2(tmp);
}

Call by Value와 Call by Reference 둘다 함수 안에서 Object 를 전송할경우 복사가 이루어진다. 

 

하지만 R Value로 구현하면 얘기는 달라진다.

 

void Test3(std::string&& str)				// 복사 안함
{
	//std::string strRE = str; // Error
    std::string strRV = std::move(str);		// 복사 암함
}

int main()
{
	Test3("Test");
}

 

받는것은 RValue  타입으로 받고 이것을 R Value로 받을수 있게 해주어 복사가 이루어 지지 않게 해준다. 

 

이게 무슨 말인지 어려울것이다. 밑에 그림을 봐주면 그나마 이해가 쉬울것이라 생각된다.

 

Call by Value

1. 먼저 tmp 변수는 Test 힙데이터를 가르킨다.

2. 함수 호출 후 str은 복사된 Test를 가르킨다.

3. 마지막으로 strV에 str가 가르키는 Test를 복사한다.

 

Call by Reference

1. tmp변수는 Test 데이터를 가르킨다.

2. str참조 변수는 tmp가 가르키는 Test데이터를 가르킨다.

3. strRef는 str이 가르키는 Test데이터를 복사해서 가르킨다.

 

R Value

1. Test라는 임시 데이터를 만든다. 

2. str에서 임시데이터인 Test를 가르킨다.

3. strRV에서는 str이 가르키는 Test를 가르킨다.

* std::move에 의해 str이 가르키는 Test의 소유권이 strRV로 넘어가며 str엔 데이터가 없어지게 된다.

'C++ > C++11' 카테고리의 다른 글

C++11 특징 (std::pair, std::tuple)  (0) 2021.03.10
C++11 특징 (Uniform 초기화)  (0) 2021.03.05
C++11 특징 (lambda)  (0) 2021.03.03
C++11 특징( ranged for loop)  (0) 2021.03.03
C++11 특징 (auto)  (0) 2021.03.02
:

이제부터는 새로 알아가는 내용들이 될꺼 같다. 

 

단순히 초기화할때 () 소괄호가 아닌 {} 대괄호로 초기화하는게 추가 된건가했다.

 

굳이 왜 초기화할때 소괄호로만 해도 되는데 대괄호가 추가된것일까? 라는 생각을 가졌는데 확인해보니 암시적 변환이 되면 안되는 것에 대해선 {} 대괄호로 처리하는 것으로 보인다.

 

실사용에서 아직 사용하지 않아서 이정도만 알꺼 같다.

 

class A
{
public:
	A(int a) {}
};



A a(5);			//기존 초기화
A b{ 5 };		//Uniform 초기화
A c{ 5.2 };		//Uniform 초기화 이지만 인자가 float 이나 dobule로 암시적 변환을 시도하기에 에러

'C++ > C++11' 카테고리의 다른 글

C++11 특징 (std::pair, std::tuple)  (0) 2021.03.10
C++ 11 특징 ( R Value)  (0) 2021.03.09
C++11 특징 (lambda)  (0) 2021.03.03
C++11 특징( ranged for loop)  (0) 2021.03.03
C++11 특징 (auto)  (0) 2021.03.02
:

C++11 특징 (lambda)

2021. 3. 3. 23:02

기본적인 람다식은 아래와 같다.

 

[ introducer capture ]( parameters ){ statement };

 

람다식은 처음에 나왔을때 어디에 써먹지라는 생각이 났다. 함수호출용? 이라기엔 하나의 함수 스코프에서만 쓸수 있는것이고 사용하기에 따라 다르지만 내가 하는 작업과는 맞지 않는다고 생각했다.

 

물론 이후에 C++14, 17, 20까지 나오고 있는 상황에선 지금 적는거보단 훨씬 많은 쓰임새가 있을꺼 같다.

 

그러다 함수 포인터 전달용으로 쓰면 어떨까라는 생각을 하게 됐다. 나중에 적을 function 이지만 미리 적겠다.

int Add(int a, int b)
{
	return a + b;
}

//기존 함수 형식으로 작성
std::function<int(int, int)> pFunc = std::bind(Add, std::placeholders::_1, std::placeholders::_2);

//람다식 이용
std::function<int(int, int)> pFunc2 = [](int a, int b) { return Add(a, b); }

해당 식을 작성 후 다른 클래스에 넘겨준 후 해당 함수를 호출하면 된다. 

'C++ > C++11' 카테고리의 다른 글

C++11 특징 (std::pair, std::tuple)  (0) 2021.03.10
C++ 11 특징 ( R Value)  (0) 2021.03.09
C++11 특징 (Uniform 초기화)  (0) 2021.03.05
C++11 특징( ranged for loop)  (0) 2021.03.03
C++11 특징 (auto)  (0) 2021.03.02
:

C++11 중 마음에 들기도 하고 아니기도 한 문법이다. 

 

std::vector<int> vArray;

vArray.push_back(1);
vArray.push_back(2);
vArray.push_back(3);
vArray.push_back(4);

//기본 형식
for(auto iter : vArray)
	std::cout << iter;
    
//참조 형식
for(auto& iter : vArray)
	std::cout << iter;
    
//const 참조 형식
for(const auto& iter : vArray)
	std::cout << iter;

기본 형식이 있지만 cosnt 참조 형식을 주로 쓰게 된다. 아무래도 기본 형식으로 하면 값을 복사하여 사용하기 때문일 것이다. 그렇다고 참조 형식으로 하면 값의 변경이 생길수 있다.

 

해당 형식은 STL 형식에서만 사용 가능해보인다. 이런게 있다고 하면 배열에 넣고 해봤더니 안된다. STL에 반복자만 가능한가 보다 (아닐수도..)

 

사용하면서 불편했던점은 인덱스 접근할때 난감할때가 있다. 그것을 어떻게든 해결만 하면 좋을꺼 같다.

'C++ > C++11' 카테고리의 다른 글

C++11 특징 (std::pair, std::tuple)  (0) 2021.03.10
C++ 11 특징 ( R Value)  (0) 2021.03.09
C++11 특징 (Uniform 초기화)  (0) 2021.03.05
C++11 특징 (lambda)  (0) 2021.03.03
C++11 특징 (auto)  (0) 2021.03.02
:

C++11 특징 (auto)

2021. 3. 2. 22:17

 

컴파일 타임에 type이 결정이 되며 현재까진 대부분의 타입이 정의 된다.

//자료형

auto Name = "yoem"; ==> char*

auto Num = 1; ==> int

auto Name     = "Yoem";          //char*
auto Num    = 1;            //int

int Num2 = 4;
auto* pNum2 = &Num2;        //int*
auto& refNum2 = Num2;         //Reference

class A
{
};

auto pA = new A();            // Class A Pointer

하지만 막상 사용해보면 자료형용만 쓰면 단점이 있었다. 가장 큰 단점으로 보인것은 아무래도 코드 수정중 해당 타입이 무엇인지 한번에 알기 어려웠다. 물론 찾아가면 알수 있지만 보자마자 아 이것 무슨 형식이구나 하는 시간이 걸렸고 그래서 위의 형태로는 잘 사용을 안하게 되었다. 그렇다면 어떻게 사용할까 현재까지는 위의 형식 말고 전부라고 해도 될꺼 같다.

//Iterator
std::vector vArray;

vArray.push_back(1);
vArray.push_back(2);
vArray.push_back(3);

for(auto iter = vArray.begin(); iter != vArray.end(); iter++)
{
}

//lambda
void Add(int a, int b)
{
	return a+b;
}

auto Func = [](int a, int b){ return Add(a,b); };
int nNum = Func(4,5);

형식으로 사용한다. iterator 형식은 auto로 사용안하게 되면 

 

std::vector<int>::const_iterator

 

형식으로 써야하는데 저걸 단 4 글자로 줄일수 있는것이다. 또한 lambdb도 함수 포인터 형식으로 했는데 iterator와 마찬가지로 글자수를 많이 줄여줄수 있다. 

'C++ > C++11' 카테고리의 다른 글

C++11 특징 (std::pair, std::tuple)  (0) 2021.03.10
C++ 11 특징 ( R Value)  (0) 2021.03.09
C++11 특징 (Uniform 초기화)  (0) 2021.03.05
C++11 특징 (lambda)  (0) 2021.03.03
C++11 특징( ranged for loop)  (0) 2021.03.03
:
/*

LambdaSearch.h

*/

typedef struct _SERACH

{

int x;

int y;

}SEARCH;



class Search_Test

{

private:

std::vector m_vSearch;

public:

SEARCH* lambdaSearch(const int x, const int y);

}





/*

LambdaSearch.cpp

*/



SEARCH* Search_Test::lambdaSearch(const int x, const int y)

{

	auto pData = std::find_if(m_vSearch.begin(), m_vSearch.end(), [=](const SEARCH* pData){ return pData->x == x && pData->y== y; });

	

	if (pData == m_vSearch.end())

		return nullptr;



	return *pData;



}

'C++' 카테고리의 다른 글

맴버 초기화 리스트  (0) 2021.03.23
xmllite 설정하기  (0) 2013.08.15
:


   
CoInternetSetFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS,
			SET_FEATURE_ON_PROCESS, true);
:

BLOG main image
by 한그릇더

공지사항

카테고리

분류 전체보기 (30)
C++ (16)
C# (0)
시스템프로그램이 (2)
Android (0)
리눅스 (2)
Etc (8)
Meanstack (1)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

태그목록

글 보관함

달력

«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Total :
Today : Yesterday :