항목 6: 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해버리자
·
STUDY/Effective C++
항목5를 보면 알 수 있다시피 컴파일러는 클래스에 대해 기본생성자, 복사 생성자, 복사 대입 연산자, 소멸자를 암시적으로 만들 수 있다. 그러면 복사가 되지않게 복사 생성자 자체를 만들지 않을 수 없는걸까? 1. 해당 멤버함수를 private으로 선언 class HomeForSale { public: ... private: ... HomeForSale(const HomeForSale&); HomeForSale& operator=(const HomeForSale&); }; 결론은 컴파일러에서 자동으로 생성하는것을 방지하고자하는 멤버함수를 따로 private으로 선언만하고 구현을 하지않으면 되는일이다. 2. Uncopyable 상속 class Uncopyable { protected: Uncopyable()..
항목 5: C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자
·
STUDY/Effective C++
컴파일러는 우리를 대신해서 기본생성자, 복사생성장, 복사 대입 연산자, 소멸자 등 기본형 함수를 만들어낸다. 하지만 의 경우에는 std::string newDog("Persephone"); std::string oldDog("Satch"); NameObject p(newDog, 2); NameObject s(oldDog, 36); p=s; 참조자 p는 원래 자신이 참조하고 있는것과 다른 객체를 참조할 수 없다. 그렇다고 값 자체가 바뀌는것은 대입연산에 직접관여하지 않는 객체(string에 대한 포인터나 참조자를 품는 다른 객체들)까지 영향을 받게된다. 그렇게 된다면 컴파일 거부가 뜰 수 있다. 이럴 경우를 대비해서 복사 대입 연산자의 경우에는 직접 정의를 해야한다.
항목 4: 객체를 사용하기 전에 반드시 그 객체를 초기화하자
·
STUDY/Effective C++
대입(assignment)과 초기화(initialization)를 헷갈리지않기 class People {...}; class Person { public: Person(const std::string& name, const std::int& age); private: std::string theName; std::string theAge; }; Person::Person(const std::string& name, const std::int& age) { theName = name; theAge = age; } 위 코드는 초기화가 아니라 대입이다. Person::Person(const std::string& name, const std::int& age) : theName(name), theAge(age..
항목 3: 낌새만 보이면 const를 들이대 보자!
·
STUDY/Effective C++
const의 장점 - 클래스 바깥에서 전역 혹은 네임스페이스 유표범위의 상수를 선언하는데 쓸 수 있다. - 파일, 함수, 블록 유효범위에서 static으로 선언한 객체에도 const를 붙일 수 있다. - 클래스 내부에서 정적 멤버 및 미정적 데이터 멤버 모두를 상수로 선언할 수 있다. - 포인터 자체를 상수로, 포인터가 가리키는 데이터를 상수로 지정할 수 있다. 상수 포인터 char greeting[] = "Hello"; char *p = greeting; //비상수 포인터, 비상수 데이터 const char *p = greeting;// 비상수 포인터, 상수 데이터 char * const p = greeting; //상수 포인터, 비상수 데이터 const char* const p = greeting; ..