C++ TIL day 10

2024. 12. 30. 20:54·C++

1. 코딩 스탠다드 

  • 코드를 짤때 더 가독성 좋은, 유지보수 할 수 있는 코드를 만들고 싶어서 C++ 코딩 스탠다드에 대해 공부해 보았다.
  • https://gbleem.tistory.com/13
 

C++ 코딩 스탠다드

0. 코딩 스탠다드를 지켜보자코딩을 하다보니 이름 규칙이나 변수명 등을 정리하지 못하고 짓고 있는 것 같아서 이번 과제를 하면서는 코딩 스탠다드를 지켜보자는 생각에 C++ 코딩 스탠다드를

gbleem.tistory.com

 

2. 템플릿

  • ch2 3번 과제를 하던 도중 
  • 템플릿을 이용한 클래스를 만드는데, 선언을 .h에 하고 구현을 .cpp에 하니 문제가 발생하였다.
  • 이를 해결하고 원인에 대해 공부해 보았다.
  • https://gbleem.tistory.com/14
 

C++ 템플릿 - 헤더파일에서 구현하자

과제를 하던 도중, 템플릿을 사용하여 vector 클래스를 만들고 있는데 .h 파일에서 정의를 하고 .cpp에서 구현을 하였더니 컴파일러가 링크 에러를 띄워주었다. (LNK1120)이 문제점을 분석하고, 찾은

gbleem.tistory.com

3. 과제 풀이

  • 필수 기능 구현
    • SimpleVector.h 와 main.cpp의 모습
    • 위에서 언급한대로 템플릿으로 만들어진 클래스의 구현은 헤더파일에서 하는 것이 좋다.
#pragma once

#include <iostream>

template <typename T>
class SimpleVector
{
public:
	SimpleVector();
	SimpleVector(int capacity);
	~SimpleVector();

	void PushBack(const T& value);
	void PopBack();

	int GetSize()
	{
		return mCurrentSize;
	}
	int GetCapacity() 
	{
		return mcurrentCapacity; 
	}

	void Print()
	{
		if (mCurrentSize == 0)
			std::cout << "EMPTY VECTOR";

		for (int i = 0; i < mCurrentSize; ++i)
		{
			std::cout << mData[i] << " ";
		}
		std::cout << "\n";
	}

private:
	T* mData;
	int mCurrentSize;
	int mcurrentCapacity;
};

template <typename T>
SimpleVector<T>::SimpleVector()
	:mcurrentCapacity(10)
	, mCurrentSize(0)
{
	mData = new T[10];
}

template <typename T>
SimpleVector<T>::SimpleVector(int capacity)
	:mcurrentCapacity(capacity)
	, mCurrentSize(0)
{
	mData = new T[capacity];
}

template<typename T>
SimpleVector<T>::~SimpleVector()
{
	mcurrentCapacity = 0;
	mCurrentSize = 0;

	delete[] mData;
}

template<typename T>
void SimpleVector<T>::PushBack(const T& value)
{
	if (mCurrentSize >= mcurrentCapacity)
	{
		std::cout << "not enough capacity\n";
		return;
	}
	mData[mCurrentSize] = value;
	mCurrentSize++;
}

template<typename T>
void SimpleVector<T>::PopBack()
{
	if (mCurrentSize == 0)
	{
		std::cout << "Empty vector!!\n";
		return;
	}

	mCurrentSize--;
}
#include "SimpleVector.h"

int main()
{
	SimpleVector<int> vector(5);

	vector.PushBack(10);
	vector.PushBack(20);
	vector.PushBack(30);
	vector.PushBack(40);
	vector.PushBack(50);

	vector.Print(); //10 20 30 40 50

	vector.PopBack();
	vector.Print(); //10 20 30 40

	vector.PopBack();
	vector.Print(); //10 20 30

	vector.PopBack();
	vector.Print(); //10 20

	vector.PopBack();
	vector.Print(); //10

	vector.PopBack();
	vector.Print(); // EMPTY VECTOR

	vector.PopBack(); //Empty vector!!
	vector.Print(); //EMPTY VECTOR

	vector.PushBack(100);
	vector.PushBack(200);
	vector.PushBack(300);

	vector.Print(); //100 200 300
	return 0;
}
  • 도전 기능 구현
    • 동작은 제대로 하는데, 메모리 누수 체크를 해보는 도중 메모리 누수가 발생한다고 떠서 좀 더 수정이 필요해 보인다.
    • 메모리 누수 체크를 하는 코드를 아직 정확하게 이해하지 못해서 그런것인지, 아니면 진짜 누수가 일어나는 것인지 확인이 필요하다.
#pragma once
#define _CRTDBG_MAP_ALLOC

#include <algorithm>
#include <iostream>

#ifdef _DEBUG
	#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

template <typename T>
class BetterSimpleVector
{
public:
	BetterSimpleVector();
	BetterSimpleVector(int capacity);
	BetterSimpleVector(const BetterSimpleVector& other);
	~BetterSimpleVector();

	void PushBack(const T& value);
	void PopBack();
	void Print();
	void SortData();

	int GetSize()
	{
		return mCurrentSize;
	}
	int GetCapacity()
	{
		return mCurrentCapacity;
	}

protected:
	void Resize(int newCapacity);

private:
	T* mData;
	int mCurrentCapacity;
	int mCurrentSize;
};

template <typename T>
BetterSimpleVector<T>::BetterSimpleVector()
	: mCurrentCapacity(10)
	, mCurrentSize(0)
{
	mData = new T[10];
}

template <typename T>
BetterSimpleVector<T>::BetterSimpleVector(int capacity)
	: mCurrentCapacity(capacity)
	, mCurrentSize(0)
{
	mData = new T[capacity];
}

template<typename T>
BetterSimpleVector<T>::BetterSimpleVector(const BetterSimpleVector& other)
{	
	mCurrentCapacity = other.mCurrentCapacity;
	mCurrentSize = other.mCurrentSize;

	mData = new T[mCurrentCapacity];

	for (int i = 0; i < mCurrentSize; ++i)
	{
		mData[i] = other.mData[i];
	}
}

template<typename T>
BetterSimpleVector<T>::~BetterSimpleVector()
{
	mCurrentCapacity = 0;
	mCurrentSize = 0;
	
	delete[] mData;	

	_CrtDumpMemoryLeaks();
}

template<typename T>
void BetterSimpleVector<T>::PushBack(const T& value)
{	
	//full
	if (mCurrentSize == mCurrentCapacity)
	{
		Resize(mCurrentCapacity + 5);				
	}
	
	mData[mCurrentSize] = value;
	mCurrentSize++;
}

template<typename T>
void BetterSimpleVector<T>::PopBack()
{
	if (mCurrentSize == 0)
	{
		std::cout << "Empty vector!!\n";
		return;
	}

	mCurrentSize--;
}

template<typename T>
void BetterSimpleVector<T>::Print()
{
	if (mCurrentSize == 0)
	{
		std::cout << "EMPTY VECTOR";
		return;
	}

	for (int i = 0; i < mCurrentSize; ++i)
	{
		std::cout << mData[i] << " ";
	}
	std::cout << "\n";
}

template<typename T>
void BetterSimpleVector<T>::SortData()
{	
	std::sort(mData, mData + mCurrentSize);	
}

template<typename T>
void BetterSimpleVector<T>::Resize(int newCapacity)
{
	if (newCapacity <= mCurrentCapacity)
	{
		std::cout << "we have remain capacity\n";
		return;
	}
	std::cout << "Resize Vector, current capacity is " << newCapacity << "\n";

	T* newData = new T[newCapacity];

	//현재 값 복사
	for (int i = 0; i < mCurrentSize; ++i)
	{
		newData[i] = mData[i];
	}

	delete[] mData;	

	mData = newData;	
	mCurrentCapacity = newCapacity;	

	_CrtDumpMemoryLeaks();
}
#include <iostream>

#include "SimpleVector_v2.h"

int main()
{	
	BetterSimpleVector<int> vector2;
	BetterSimpleVector<int> vector(3);

	vector.PushBack(10);
	vector.PushBack(40);
	vector.PushBack(30);
	vector.PushBack(50);
	vector.PushBack(20);

	std::cout << "vector: ";
	vector.Print();
	
	vector2.PushBack(100);
	vector2.PushBack(200);
	vector2.PushBack(300);
	vector2.PushBack(400);
	vector2.PushBack(500);

	vector2.PushBack(600);
	vector2.PushBack(700);
	vector2.PushBack(800);
	vector2.PushBack(900);
	vector2.PushBack(1000);
	vector2.PushBack(1100);

	std::cout << "vector2: ";
	vector2.Print();

	BetterSimpleVector<int> newVector(vector2);
	std::cout << "----COPY CONSTRUCTOR TEST----\n";
	std::cout << "newVector by vector2: ";
	newVector.Print();
	std::cout << "---------------------\n";

	BetterSimpleVector<int> vector3(3);
	vector3.PushBack(1);
	vector3.PushBack(2);
	vector3.PushBack(3);

	std::cout << "vector3: ";
	vector3.Print();

	BetterSimpleVector<int> newVector2(vector3);
	std::cout << "----COPY CONSTRUCTOR TEST----\n";
	std::cout << "newVector2 by vector3: ";
	newVector2.Print();
	std::cout << "---------------------\n";

	newVector2.PushBack(4);
	newVector2.PushBack(5);
	newVector2.PushBack(6);

	std::cout << "newVector2: ";
	newVector2.Print();

	vector3.PushBack(1);
	std::cout << "vector3: ";
	vector3.Print();

	return 0;
}

위의 코드 실행 결과

4. 내일 할 것

  • const 키워드 정리
  • 메모리 누수 체크 코드 공부 및 과제에서 발생한 문제점을 찾기 (해결)
  •  inline 함수 공부

5. 메모리 누수 체크

  • 뭐가 잘못된 것이지 좀 더 찾아보다가 해결책을 찾게 되었다.
  • 위의 코드에서 메모리 누수가 발생한 것은 내가 잘못된 곳에서 _CrtDumpMemoryLeaks() 를 호출했기 때문이다.
  • main 에서 프로그램 종료시 호출되도록 구현해야 제대로 된 memory leak을 찾을 수 있다.
  • 관련 코드 정리해 보자면,
    • 우선 위의 코드에서  _CrtDumpMemoryLeaks()는 다 없애버려야 한다.
    • 헤더 파일에 new 매크로를 사용해서, 메모리 누수가 발생한 곳의 위치를 알려주는 코드를 추가한다.
    • main 함수에 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);를 적어주면, 추가적인 다른 처리없이 프로그램 종료 시 메모리 누수 발생 시 어디서 발생한 것인지 알려주게 된다.
//header file 
#define _CRTDBG_MAP_ALLOC

#ifdef _DEBUG
	#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
...

//main.cpp
...
int main()
{	
#ifdef _DEBUG
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
...
}
  • 아래에서 어떤 식으로 메모리 누수를 알려주는 지 예시를 통해 확인해보자
    • 왼쪽은 .h 파일이고 오른쪽은 .cpp 파일이다.
    • 위에서 언급한 대로 구성한 코드에 아래 처럼 강제로 메모리 누수가 발생하는 코드를 넣으면
    • 아래 이미지처럼 메모리 누수가 발생했고, 몇번째 줄에서 발생했는지 알려주게 된다.

  • 저 코드를 main에서 주석처리해버리면 아래처럼 메모리 누수가 일어나지 않는 것을 알 수 있다.
    • cf) 코드를 추가하고 나서 비주얼 스튜디오의 "빌드 -> 솔루션 다시 빌드" 를 해줘야 수정한 것이 제대로 적용되는 것 것 같다.

  • 결론적으로 위에서 완성한 코드는 메모리 누수가 없는 코드라고 생각이 되었다. 그래도 혹시 모르니 제출 전 한번 더 체크해 볼 예정이다.

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

C++ TIL day 11 (포인터 연산 문제)  (2) 2024.12.31
const 키워드  (0) 2024.12.31
C++ 템플릿 - 헤더파일에서 구현하자  (0) 2024.12.30
C++ 코딩 스탠다드  (2) 2024.12.30
C++ TIL day 9  (3) 2024.12.27
'C++' 카테고리의 다른 글
  • C++ TIL day 11 (포인터 연산 문제)
  • const 키워드
  • C++ 템플릿 - 헤더파일에서 구현하자
  • C++ 코딩 스탠다드
gbleem
gbleem
gbleem 님의 블로그 입니다.
  • gbleem
    gbleem 님의 블로그
    gbleem
  • 전체
    오늘
    어제
    • 분류 전체보기 (184)
      • Unreal Engine (73)
      • C++ (19)
      • 알고리즘(코딩테스트) (27)
      • TIL (60)
      • CS (4)
      • 툴 (1)
  • 블로그 메뉴

    • 홈
    • 카테고리
  • 링크

    • 과제용 깃허브
    • 깃허브
    • velog
  • 공지사항

  • 인기 글

  • 태그

    addonscreendebugmessage
    map을 vector로 복사
    applydamage
    BFS
    actor 클래스
    enhanced input system
    DP
    Vector
    C++
    additive animation
    상속
    싱글턴
    blend pose
    motion matching
    템플릿
    gamestate
    cin함수
    const
    매크로 지정자
    character animation
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gbleem
C++ TIL day 10
상단으로

티스토리툴바