함수에 원래 변수를 제공 할 때 더 나은 방법은 무엇입니까?
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
또는:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW : 다른 것을 골라야 할 이유가 있습니까?
함수에 원래 변수를 제공 할 때 더 나은 방법은 무엇입니까?
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
또는:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW : 다른 것을 골라야 할 이유가 있습니까?
답변:
내 경험 법칙은 다음과 같습니다.
포인터를 사용하여 포인터 산술을 수행하려는 경우 (예 : 포인터 주소를 배열을 통해 증가시키기 위해) 또는 NULL 포인터를 전달해야하는 경우 포인터를 사용하십시오.
그렇지 않으면 참조를 사용하십시오.
Base* b = new Derived()
어떻습니까? 이것은 포인터없이 처리 할 수없는 경우처럼 보입니다.
코딩 가이드 라인을 호출하는 다음 함수를 설정하면 도움이 될 것이라고 생각합니다.
다른 모든 장소와 마찬가지로 항상 const
정확해야합니다.
const
지정자가 부족함을 의미 합니다.현재 컨텍스트에서 0 / NULL 값이 유효한 입력 인 경우에만 포인터로 값을 전달하십시오.
근거 1 : 발신자 로서 , 당신은 당신이 전달하는 것이 사용 가능한 상태 에 있어야 한다는 것을 알 수 있습니다.
이유 2 :로는 전화 당신이 들어오는 어떤 것을 알고, 이다 가능한 상태. 따라서 해당 값에 대해 NULL 검사 또는 오류 처리를 수행 할 필요가 없습니다.
이론적 근거 3 : 이론적 근거 1과 2가 컴파일러에 의해 시행 될 것이다 . 가능하면 컴파일 타임에 항상 오류를 잡으십시오.
함수 인수가 값을 벗어나면 참조로 전달하십시오.
값이 POD ( Plain old Datastructure )이거나 작거나 (메모리 단위) 또는 다른 방법으로 복사 할 수있을만큼 (시간 단위) 값이 작은 경우에만 "pass by const reference"대신 "value by pass"를 선택하십시오 .
std::vector<>
입니다.
이것은 결국 주관적입니다. 지금까지의 논의는 유용하지만 이것에 대한 정답이나 결정적인 대답은 없다고 생각합니다. 많은 것은 스타일 가이드 라인과 당시의 요구에 달려 있습니다.
포인터와 함께 몇 가지 다른 기능 (무엇이 NULL이 될 수 있는지 여부)이 있지만 출력 매개 변수의 실질적인 차이점은 순전히 구문입니다. 예를 들어 Google의 C ++ 스타일 가이드 ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments )는 출력 매개 변수에 대한 포인터 만 요구하고 const 인 참조 만 허용합니다. 추론은 가독성 중 하나입니다. 값 구문이있는 것은 포인터 의미 의미를 가져서는 안됩니다. 나는 이것이 반드시 옳고 그름이라고 제안하지는 않지만, 여기서 요점은 그것이 정확성이 아니라 스타일의 문제라는 것입니다.
변수 값을 수정하려면 포인터를 전달해야합니다. 기술적으로 참조 또는 포인터를 전달하는 것은 동일하지만 사용 사례에서 포인터를 전달하면 값이 함수에 의해 변경된다는 사실을 "광고"하므로 더 읽기 쉽습니다.
const
또는 비 const
참조를,하지만 당신은 매개 변수의이 ALA 통과하면 볼 수 &x
대를 x
, 사용 매개 변수가 수정되기 쉬운 지 여부를 인코딩하기 위해이 컨버전스. ( const
포인터 를 전달하고 싶을 때가있다 . 그래서 확신은 단지 힌트 일 뿐이다. 그렇지 않을 때 무언가를 의심하는 것은 의심 할 여지가 없다고 생각하는 것보다 덜 위험 할 수있다. ....)
값이 없음을 표시해야하는 매개 변수가있는 경우 매개 변수를 포인터 값으로 만들고 NULL로 전달하는 것이 일반적입니다.
대부분의 경우 (안전 측면에서) 더 나은 솔루션은 boost :: optional 을 사용하는 것 입니다. 이를 통해 참조 값과 반환 값으로 선택적 값을 전달할 수 있습니다.
// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
if (optional_str)
{
cout << *optional_str << std::endl;
}
else
{
cout << "(no string)" << std::endl;
}
}
// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
if (return_nothing)
{
return boost::optional<int>();
}
return boost::optional<int>(42);
}
가능하면 참조를 사용하고, 필요할 때 포인터를 사용하십시오. 에서 C ++ FAQ : "나는 포인터를 사용해야 할 때 언제 참조를 사용한다?"
포인터
현재 유효한 메모리 위치를 가리 키지 않는 포인터에는 null 값이 제공됩니다 (0 인 경우).
BaseType* ptrBaseType;
BaseType objBaseType;
ptrBaseType = &objBaseType;
&는 피연산자의 메모리 주소를 반환하는 단항 연산자입니다.
역 참조 연산자 (*)는 포인터가 가리키는 변수에 저장된 값에 액세스하는 데 사용됩니다.
int nVar = 7;
int* ptrVar = &nVar;
int nVar2 = *ptrVar;
참고
참조 (&)는 기존 변수의 별칭과 같습니다.
참조 (&)는 자동으로 역 참조되는 상수 포인터와 같습니다.
일반적으로 함수 인수 목록 및 함수 반환 값에 사용됩니다.
참조를 만들 때 초기화해야합니다.
객체에 대한 참조가 초기화되면 다른 객체를 참조하도록 변경할 수 없습니다.
NULL 참조는 가질 수 없습니다.
const 참조는 const int를 참조 할 수 있습니다. const 값을 가진 임시 변수로 수행됩니다.
int i = 3; //integer declaration
int * pi = &i; //pi points to the integer i
int& ri = i; //ri is refers to integer i – creation of reference and initialization
참조는 암시 적 포인터입니다. 기본적으로 참조가 가리키는 값을 변경할 수 있지만 다른 것을 가리 키도록 참조를 변경할 수는 없습니다. 따라서 2 센트는 매개 변수의 값만 변경하려면 참조로 전달하지만 다른 객체를 가리 키도록 매개 변수를 변경 해야하는 경우 포인터를 사용하여 매개 변수를 전달해야한다는 것입니다.
포인터 :
nullptr
(또는 NULL
).&
유형이 포인터 자체가 아닌 경우 객체를 수정하고 명시 적으로 작성해야합니다.참고 문헌 :
&
. 매개 변수가 수정되었는지 확인하려면 함수 구현으로 이동해야하기 때문에 때로는 나쁜 것으로 간주됩니다.