포인터 대 참조

함수에 원래 변수를 제공 할 때 더 나은 방법은 무엇입니까?

unsigned long x = 4;

void func1(unsigned long& val) {
     val = 5;            
}
func1(x);

또는:

void func2(unsigned long* val) {
     *val = 5;
}
func2(&x);

IOW : 다른 것을 골라야 할 이유가 있습니까?



답변

내 경험 법칙은 다음과 같습니다.

포인터를 사용하여 포인터 산술을 수행하려는 경우 (예 : 포인터 주소를 배열을 통해 증가시키기 위해) 또는 NULL 포인터를 전달해야하는 경우 포인터를 사용하십시오.

그렇지 않으면 참조를 사용하십시오.


답변

코딩 가이드 라인을 호출하는 다음 함수를 설정하면 도움이 될 것이라고 생각합니다.

  1. 다른 모든 장소와 마찬가지로 항상 const정확해야합니다.

    • 참고 : 이는 특히 값을 벗어난 값 (항목 3 참조)과 값을 통해 전달 된 값 (항목 4 참조) 만 const지정자가 부족함을 의미 합니다.
  2. 현재 컨텍스트에서 0 / NULL 값이 유효한 입력 인 경우에만 포인터로 값을 전달하십시오.

    • 근거 1 : 발신자 로서 , 당신은 당신이 전달하는 것이 사용 가능한 상태 에 있어야 한다는 것을 알 수 있습니다.

    • 이유 2 :로는 전화 당신이 들어오는 어떤 것을 알고, 이다 가능한 상태. 따라서 해당 값에 대해 NULL 검사 또는 오류 처리를 수행 할 필요가 없습니다.

    • 이론적 근거 3 : 이론적 근거 1과 2가 컴파일러에 의해 시행 될 것이다 . 가능하면 컴파일 타임에 항상 오류를 잡으십시오.

  3. 함수 인수가 값을 벗어나면 참조로 전달하십시오.

    • 근거 : 우리는 아이템 2를 깨고 싶지 않다 …
  4. 값이 POD ( Plain old Datastructure )이거나 작거나 (메모리 단위) 또는 다른 방법으로 복사 할 수있을만큼 (시간 단위) 값이 작은 경우에만 “pass by const reference”대신 “value by pass”를 선택하십시오 .

    • 근거 : 불필요한 사본을 피하십시오.
    • 참고 : 작은 충분 하고 저렴한 충분 절대 measurables 수 없습니다.

답변

이것은 결국 주관적입니다. 지금까지의 논의는 유용하지만 이것에 대한 정답이나 결정적인 대답은 없다고 생각합니다. 많은 것은 스타일 가이드 라인과 당시의 요구에 달려 있습니다.

포인터와 함께 몇 가지 다른 기능 (무엇이 NULL이 될 수 있는지 여부)이 있지만 출력 매개 변수의 실질적인 차이점은 순전히 구문입니다. 예를 들어 Google의 C ++ 스타일 가이드 ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments )는 출력 매개 변수에 대한 포인터 만 요구하고 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