C++당신 은 몇 가지 작은 매듭 을 하지 않 는 것 이 좋 습 니 다.
6706 단어 안 하 는 게 좋 을 것 같 아 요.
어떤 학생 이 전달 하 는 매개 변 수 를 인용 방식 으로 전달 하여 임시 대상 의 생 성 을 피하 고 효율 을 높 였 습 니 다.그러면 값 을 되 돌 릴 때 인용 을 사용 할 수 있 습 니까?
다음 코드 보기
class Rational{
public:
Raional( int numerator = 0, int denominator =1);
...
private:
int d, d;
friend Rational operator* (const Rational& lhs, const Raional& rhs) ;
};
Rational Rational::operator* (const Rational& lhs,const Raionl&rhs)
{
return Rational result(lhs.n*rhs.n,lhs.d*rhs.d);
}
}
이 종 류 는 바로 우리 가 앞에서 소개 한 유리수 류 이다.여기 서 생각해 보면 한 번 의 구조 와 유형의 분석 구조 가 발생 할 것 이다.그러면 인용 을 사용 하면 이 문 제 를 피 할 수 있 을 까?효율 을 높 일 수 있 습 니까?함수 가 새 대상 을 만 드 는 방법 은 두 가지 가 있 습 니 다.하 나 는 스 택(statck)에서 만 드 는 것 이 고 하 나 는 쌓 기(heep)에서 만 드 는 것 입 니 다.
People p(a,b) //
People *p = new People(a,b) //
현재 스 택 에서 만 드 는 것 을 먼저 고려 하지만 이 생 성 된 변 수 는 부분 변수 로 함수 가 종료 되 기 전에 삭 제 됩 니 다.
const Rational& operator* (const Rational& lhs, const Rational & rhs)
{
Rational result(lhs.n*rhs.n,lhs.d*rhs.d);
return result;
}
함수 내 에서 stack 방식 으로 공간 을 만 드 는 대상 은 국부 대상 입 니 다.모든 함수 가 참조 가 특정한 국부 대상 을 가리 키 면 오류 가 발생 합 니 다.부분 대상 이 함수 가 종료 되 기 전에 소각 되 었 기 때문에 reference 가 가리 키 는 대상 이 존재 하지 않 음 을 의미 합 니 다. 그래서 더미 에서 만 드 는 것 을 고려 합 니 다
const Rational& operator* (const Rational& lhs, const Rational & rhs)
{
Rational* result=new Rational(lhs.n*rhs.n,lhs.d*rhs.d);
return *result;
}
지금 또 하나의 문제 가 발견 되 었 습 니 다.new 에서 나 온 대상 은 누가 delete 합 니까?좋 습 니 다.이 문 제 를 선점 할 때 다음 상황 을 고려 하지 않 습 니 다
Rational w,x,y,z;
w=x*y*z;
여기 서 동시에 한 문장 이 operator*를 두 번 호출 한 것 은 new 가 두 번 호출 되 었 음 을 의미 하 며 delete 가 두 번 필요 합 니 다.그러나 이 곳 에 서 는 opertaor*사용자 에 게 delete 호출 을 할 수 있 는 합 리 적 인 방법 이 없습니다.사용자 가 되 돌아 오 는 지침 을 가 져 올 수 없 기 때문에 자원 이 누 출 될 수 있 습 니 다. 따라서 함수 내부 에 정 의 된 static Rational 대상 을 가리 키 는 인용 을 되 돌려 주 는 것 을 고려 합 니 다.
const Rational & operator*(const Rational& lhs,const Rational & rhs)
{
static Rational result;
result = ...;
return result;
}
그렇다면 다 중 스 레 드,다 중 스 레 드 환경 에서 이렇게 쓰 는 것 이 안전 합 니까?그래.다 중 스 레 드 안 끄 면그럼 다음 코드 는 어떻게 됩 니까?4567913) 상기 if 구문 표현 식 은 a,b,c,d 가 왜 true 인지 에 관 계 없 이 같은 정적 값 을 가리 키 기 때 문 입 니 다.2.모든 변 수 를 문장의 시작 에 정의 하지 않 는 것 이 좋 습 니 다.
어떤 학생 들 은 C 언어 과정 을 다 녔 을 수도 있 고 C 를 배 우 는 것 을 좋아 할 수도 있 습 니 다.모든 변 수 를 처음에 정의 하 는 것 을 좋아 합 니 다.그러나 C+에서 저 는 이렇게 하지 않 는 것 이 좋 습 니 다.변 수 를 정의 할 때 프로그램 은 구조 와 분석 을 해 야 하기 때 문 입 니 다.예 를 들 어 다음 절차 에서 우 리 는 대략 1 미터 8 이하 이 고 60 세 이하 의 학생 들 이 표를 사서 들 어 갈 수 있 도록 허락 한다.4567913)만약 에 여기 서 표를 사 는 사람의 조건 이 부합 되 지 않 는 다 면 표를 사 는 데 들 어가 정보 와 바 인 딩 작업 을 할 수 없다.그러면 여기 서 Ticket t 문 구 는 이 함수 로 하여 금 Ticket 구조 원가 와 분석 구조의 원 가 를 헛되이 받 게 한다.따라서 변 수 를 미리 정의 하지 않 고 사용 할 때 정의 하여 불필요 한 성능 소 비 를 피 하 는 것 이 좋 습 니 다.위의 예 를 아래 처럼 바 꾸 면 된다.
bool operator == (const Rational& lhs, const Rational& rhs);
...
Raional a,b,c,d;
if((a*b) == (c*d)
{
...
}
3.너무 많은 유형 전환 을 하지 않 는 것 이 좋 습 니 다.C++규칙 의 디자인 목표 중 하 나 는'유형 오류'가 발생 하지 않도록 하 는 것 이다.이론 적 으로 프로그램 은 컴 파일 을 통 해 그 어떠한 안전 하지 않 고 터 무 니 없 는 조작 도 하려 고 하지 않 는 다 는 것 을 나타 낸다.안 타 깝 게 도 유형 이 바 뀌 었 습 니 다.유형 시스템 은 어떤 종류의 번 거 로 움 을 초래 할 수 있 고 매우 번 거 로 울 수 있 습 니 다.예 를 들 어 본문의 마지막 코드 예.C 와 C++는 모두 스텔스 형식 변환 을 지원 하 는 동시에 C++는 네 가지 디 스 플레이 변환 연산 자가 있 습 니 다.멤버 함수 와 비 멤버 함수 선택 에 소개 되 어 있 습 니 다.그러나 너무 많은 유형 전환 을 하지 않 고 피 할 수 있 으 면 피 하 는 것 이 좋다.형식 변환 은 종종 당신 의 뜻 대로 되 지 않 습 니 다.먼저 예 를 들 어 보 세 요.
class People{...};
class Ticket{...};
bool Isvalid(const People&p){...}
void Banding(const People& p,Ticket& t);
Ticket buyTicket(const People& p)
{
Ticket t;
if(Isvalid(p)){ return NULL };
//
Banding(p,&t);
return t;
}
실행 결 과 는 in base a value is 5in base b value is 5a value is 2b value is 2 입 니 다.여기 서 derived 형식 을 base 로 바 꿉 니 다.그러나 base:init()함 수 는 현재 대상 의 함수 가 아니 라 이전 전환 동작 에 의 해 만들어 진'*this 대상 의 base 던 전 입 니 다.그래서 우리 가 대상 의 내용 을 바 꾸 려 고 시 도 했 을 때 사실은 던 전의 내용 을 바 꾸 었 습 니 다.그 대상 의 내용 은 바 뀌 지 않 았 습 니 다.
어떻게 이 문 제 를 해결 합 니까?기본 클래스 를 호출 하 는 함수
class People{...};
class Ticket{...};
bool Isvalid(const People&p){...}
void Banding(const People& p,Ticket& t);
Ticket buyTicket(const People& p)
{
if(Isvalid(p)){ return NULL };
Ticket t;
//
Banding(p,&t);
return t;
}
의 실행 결 과 는 다음 과 같 습 니 다:in base a value is 5in base b value is 5a value is 5b value is 5혹시 이 럴 때 dynamic 를 사용 해 야 한 다 는 것 을 기억 하 세 요?case(이전 글 을 보 았 다 면 계승 관 계 를 따라 안전하게 유형 전환 을 하 는 데 사 용 됩 니 다).dynamic 사용캐 스 트 에 직접 오류 가 발생 했 습 니 다.
#include <iostream>
class base
{
public:
base():a(0),b(0){}
base(const int& x,const int& y)
:a(x),b(y){}
virtual void init()
{
a=5;
b=5;
std::cout<<"in base a value is "<<a<<std::endl;
std::cout<<"in base b value is "<<b<<std::endl;
}
int get_a() const
{
return a;
}
int get_b() const
{
return b;
}
private:
int a;
int b;
};
class derived:public base
{
public:
derived(int x,int y):base(x,y){}
void init()
{
static_cast<base>(*this).init();
}
};
실행 결 과 는 다음 과 같 습 니 다:세그먼트 오류(메 인 메모리)정보 덤 프)는 5 층 의 단일 계승 관 계 를 가정 합 니 다.이 대상 에서 dnaic 를 실행 하면cast,그러면 다섯 번 에 달 하 는 strcmp 호출 이 있 고 깊이 나 다 중 계승 이 많 을 수록 원가 가 높 습 니 다.dynamic 가 필요 한 이유cast 는 derived class 대상 에서 derived class 조작 함 수 를 실행 하고 싶 지만,현재 base 를 가리 키 는 지침 이나 인용 만 있 습 니 다.이 때 는 이 를 사용 하여 처리 할 수 있 습 니 다.