변수가 초기화될 때 생성자와 소멸자가 호출되어 생성된다.
항목 26에서는 이조차 비용으로 정리되는 C++에서는 값을 초기화하는 타이밍을 최대한 늦추어 멤버함수 호출 빈도 관리가 비용 절감에 도움된다는 내용이다.
밑은 두가지 경우가 각각 생성자와 소멸자가 몇번 호출되는 지에 따른 비교다.
// 예제 1)
Widget W;
for(int i = 0; i < n; i++)
{
w = i;
}
// 예제 2)
for(int i = 0; i < n; i++)
{
Widget W;
}
예제 1과 예제 2번의 차이는 "Widget" 변수가 for문의 밖에서 정의되는지 안에서 정의되는지의 차이뿐이지만,
간단히 정리해보면
예제 1번 코드에서는 '생성자 1번 + 소멸자 1번 + 대입 n 번'
예제 2번 코드에서는 '생성자 n번 + 소멸자 n번'
정도의 호출이 일어난다.
스코프에 따라 생성된 변수가 초기화될 때 실행되는 함수 호출의 빈도가 비용에 영향을 주지만, 이 또한 어떤 방식이 좋을지 생각해볼 문제다.
C++ 캐스팅에는 4가지 종류가 있다.
static_cast, dynamic_cast, const_cast, reinterpret_cast 로 기존 C 스타일 캐스팅보다 C++ 스타일을 사용하면 좋은 점은
또한 항목명에서 말하는 '절약'은 캐스팅을 피하는 것이 좋으며, 사용이 불가피한 경우에는 안전하고 효율적인 방법을 사용해야 한다는 점을 강조하는 의미로, 아직까지 직접 작성한 코드던 남의 코드던 캐스팅을 사용하지 않은 코드는 한번도 보지 못했기 때문에 최대한 사용을 자제해야 한다는 의미로 받아들이면 될 것 같다.
그 이유로 캐스팅을 실행하면 런타임에 타입 변환에 필요한 코드가 작성되는데, 이 때 비용이 발생하기 때문에 추가적인 내용으로 dynamic_cast를 피해야 하는 이유는 과거 정리했던 내용이 포함되어 있다.
2024.03.25 - [C / C++] - Cast ~ static / dynamic의 소모 비용
Cast ~ static / dynamic의 소모 비용
0. 개요 4종류의 캐스트, static_cast, dynamic_cast, const_cast, ,reinterpret_cast의 기본을 알고 추가적인 내용을 작성 1. static_cast 컴파일 타임에 타입 체크를 수행해 컴파일러가 타입 안정성을 보장할 수 있
jabberworcky.tistory.com
지역성을 가진 범위에서 반환값으로 '참조자, 포인터, 반복자' 를 반환하는 것은 피하자는 내용으로 객체의 캡슐화 정도를 높이고 상수성을 유지한 체로 동작할 수 있도록 해 "참조자가 제대로 된 원본을 가리키고 있는 범위"를 벗어나 잘못된 반환값을 반환하지 않도록 해야한다.
즉, 반환된 참조자 보다 객체가 먼저 소멸해 참조자가 무엇을 가르키는지 알 수 없게 된다.
객체 내부 private 영역에 존재하는 변수나 함수의 주소, 참조자를 반환하는 코드가 이를 위반하는 행위로 const를 붙여 상수 멤버로 선언해도 마찬가지다.
예외적인 경우로, <string>이나 <vector> 클래스의 operator[] 연산자 오버로드가 참조자를 반환하는 방식으로 구현되어 있다.
예외 처리의 중요성을 강조하는 항목.
한 두번의 정독으론 정리할만큼 이해를 하지 못했다...
inline 함수는 '매크로 처럼 함수가 호출되는 부분을 inline 함수 내용으로 그대로 바꿔 실행하는 것'으로 object 파일 크기에 영향을 준다.
최신 컴파일러가 inline으로 변환하면 이득 볼 함수는 알아서 변환해준다고 하지만 이것은 프로그래머가 inline 키워드를 통해 작성한 함수도 비효율적이라면 변환하지 않는다는 뜻이다.
Unreal에서 FORECEINLINE을 통해 getter, setter를 작성하는 이유가 여기 있다고 생각한다.
매크로만큼 오버헤드 위험도 없고 매크로보다 안전하고 사용이 용이하지만, 컴파일러를 통한 inline으로의 변환은 프로그래머가 직접 의식해야 하는 부분이다.
클래스를 작성하다 보면 다른 클래스를 #include 해오는 경우가 많은데 이렇게 클래스끼리의 연결이 강해진다.
이런 부분을 "정의 대신 선언에 의존하게 만들자'는 아이디어로 시작한 "핸들 클래스"와 "인터페이스 클래스"로 대체하자는 내용이다.
이 항목에서 그에 따른 설명으로 인터페이스를 만들고 이를 가져와 구현하는 'Pimpl 관용구'를 소개한다.
// pimpl 관용구 예시 클래스
#include <string>
#include <memory>
class PersonImpl;
class Date;
class Address;
class Person
{
public:
Person(const string& name, const Date& birthday, const Address& addr);
string name() const;
string birthDate() const;
string address() const;
...
private:
shared_ptr<PersonImpl> pImpl;
};
마찬가지로 혼자 정독으로 이해가 어려웠기에 도움이 될만한 글을 기록하고 다음 정독때 다시 공부하기로 했다.
[ Effective C++ ] 항목 31 : 파일 사이의 컴파일 의존성을 최대로 줄이자
C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리
velog.io
Chapter 6. 상속, 객체지향 설계 (0) | 2024.10.08 |
---|---|
Chapter 4. 설계 및 선언 (4) | 2024.09.04 |