C++/C++

메모 (작성 중)

Elan 2021. 3. 7. 21:59

1. value type( char, int, long ... ) 포인터에  new 키워드로 메모리 할당 시


char* s = new char[500];

char* ss = new char[500]();

char* ss = new char[500]{};

위의 세 줄의 코드의 차이는 괄호의 유무이다.

괄호가 없으면 할당된 메모리의 내용을 건드리지 않는다.

빈괄호가 붙으면 할당된 메모리의 내용을 모두 0으로 초기화 한다.

C언어 에서는 괄호 (Initializer) 를 인식하지 못한다

 

문자열을 생성할 때 빈괄호 Initializer를 사용하면 마지막에 null을 추가하지 않아도 된다.

 

아래는 { } 괄호를 이용한 직접 초기화 방식이다.

int* sss = new int[500]{ 1,2,3,4,5,6,7,1,2,3, };

 

 

 

 


2. 논리연산자는 다중 정의해서는 안된다.


다중 정의할 경우 사용자에게 심각한 논리적 오류를 떠넘기는 것이다.

 

단, const가 있고, 없고의 차이만 있는 경우 다중 정의를 해도 된다.

class TestBlock {
public:
	const char& operator[](std::size_t position) const
	{		return text[position];	}//상수 객체에 대한 operator[]

	char& operator[](std::size_t position)
	{		return text[position];	}//비상수 객체에 대한 operator[]
private:
	std::string text;
};

위의 선언된 TextBlock의 operator[] 는 다음과 같이 쓸 수 있다.

TextBlock tb("Hello");
std::cout << tb[0];//비상수 멤버 호출

const TextBlock ctb("World");
std::wcout << ctb[0];//상수 멤버 호출
ctb[0]='x'; // 컴파일 에러 : 상수 객체에 대한 쓰기 불가

 

 

 

 


3. C++의 접근 지정자의 의미 ( public, protected, private )


1) protected 멤버에 대한 접근

 

C++의 Access specifier인 public, protected, private는 C#과 약간 다르므로 혼동 주의해야한다.

특히, protected 속성이 부여된 멤버는 Base class 와 Derived class의 멤버 함수에서만 접근이 가능하다.

 

class BaseClass {
public:
	BaseClass() {
		cout << "BaseClass()" << endl;
	}

	int GetData() {
		Print();
		return data;
	}

protected://Base Class or Derived Class 의 내부에서만 접근 가능
	void Print() {
		cout << "data : " << data << endl;
	}
private:
	int data = 0;
};

class DerivedClass :protected BaseClass {//protected로 상속 시 Base class 의 protected 권한 이상 멤버만 내부에서 접근 가능
public:
	DerivedClass() {
		cout << "DerivedClass()" << endl;
	}
};

위와같은 클래스가 있을 경우 protected 멤버 함수 Print()는 사용자에서 접근이 불가능하다(노출되지 않는다).

< main 문에서 protected 함수 호출 시도 >

2) Protected 상속 관계와 형변환

 파생클래스를 부모 클래스에 대입하는 것을 (업캐스팅)Up-casting 이라고 부른다.

그러나 파생 클래스와 부모 클래스의 상속관계가 public이 아닌 경우(protected, private) 얘기가 좀 달라진다.

이런 관계에서는 일반적으로 묵시적 형변환, static_cast, dynamic_cast, const_cast 가 불가능하다.

따라서 강제 형변환(C 스타일 형변환) 혹은 reinterpret_cast를 사용해야한다.

하지만 C 스타일의 강제 형변환은 많은 오류를 낳는다.

참고 - C++ 스타일 형 변환 4가지

 


4. 전위 연산자와 후위 연산자 오버로딩


전위 연산자와 후위 연산자는 매개변수가 있고 없고의 차이가 있다.

int operator++() { //매개변수 없으면 전위 연산자로 정의
	return ++data;
}

int operator++(int) {//매개변수로 연관 type을 전달하면 후위 연산자로 정의
	int nData = data;
	data++;
	return nData;
}

이처럼 후위 연산자는 임시 객체를 생성해서 반환하므로 오버헤드가 좀더 크다.

 

따라서 Iterator 사용 시 Pre-Increment/Decrement operator를 사용하는 이유도 여기에 있다.

std::array<int, 5>arr1 = { 1,2,3,4,5 };

for (auto iter = arr1.begin(); iter != arr1.end(); ++iter) {
	std::cout << *iter << endl;
}

 

연산자 오버로딩 cppreference 참고 - en.cppreference.com/w/cpp/language/operators

 

operator overloading - cppreference.com

Customizes the C++ operators for operands of user-defined types. [edit] Syntax Overloaded operators are functions with special function names: operator op (1) operator type (2) operator new operator new [] (3) operator delete operator delete [] (4) operato

en.cppreference.com


5. 클래스 생성자 호출 순서


상속 관계에서 파생클래스의 생성자는 먼저 호출되지만 실행은 나중에 된다.

 

즉, 상위 클래스의 생성자부터 실행된다.

 

 


6. std::cin 숫자만 입력받기


숫자만 입력받고 싶은데 엉뚱한 문자를 입력하는 것에 대한 예외처리를 하려면 피곤해진다.

 

간단하게 하는 방법이 있다.

 

cin의 오버로딩된 연산자 ! 를 사용하여 

int a=0;

while (a == 0) {
	cout << "숫자를 입력해주세요 : ";
	cin >> a;
	if (!cin) {
		cout << "숫자가 아닙니다!!\n";
		cin.clear();
		cin.ignore(INT_MAX, '\n');
	}
}

 

 

 


7. std::getline  개행문자 버리기


프로그램에서 입력을 받을 때 Enter키를 눌러 입력을 종료한다.

 

이때 Enter 키는 입력 버퍼에 줄바꿈 문자 '\n'으로 추가된다.

 

입력 받을 때 >> 연산자를 통해 스트림 입력 추출을 사용하는 경우 모든 공백 문자는 읽고 버리게된다.

 

 

하지만 공백을 포함하는 문자열을 입력하고 싶은 경우 std::getline을 사용하게 된다.

 

그런데 std::getline을 사용할 경우 마지막에 줄바꿈 문자 '\n'이 남는다.

 

이때 마지막 개행문자 하나 때문에 이것을 빈 줄로 인식해버린다.

 

std::ws 를 사용하여 이것을 막는 트릭이 있다.

string psuname;
getline (cin >> ws, psuname);

트릭을 원치않는다면 다른 방법을 사용하자.

 

 

 

다음은 변수에 입력을 받을 때 개행이 스트림에 남아있는 것을 막는 방법이다.

std::istream::ignore 을 사용하며 문자를 추출하고 버릴 수 있다.

#include <limits>

int x;
char str[80];

cout << "Enter a number and a string:\n";

cin >> x;

cin.ignore(numeric_limits<streamsize>::max(), '\n'); //clear buffer before taking new line
cin.getline(str, 80); //take a string

cout << "You have entered:\n";
cout << x << endl;
cout << str << endl;

 


8. 


연산자 오버로딩에서