C ++에서 포인터에 대한 참조 전달


130

내가 알 수있는 한, C ++에서 포인터에 대한 참조를 전달해서는 안되는 이유가 없습니다. 그러나 그렇게하려는 시도가 실패하고 이유를 모릅니다.

이것이 내가하고있는 일입니다.

void myfunc(string*& val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(&s);
    // ...
}

그리고 나는이 오류가 발생합니다 :

'std :: string *'에서 'std :: string * &'로 매개 변수 1을 변환 할 수 없습니다.

답변:


126

함수는 익명 문자열 포인터가 아닌 호출 범위의 실제 문자열 포인터에 대한 참조를 기대합니다. 그러므로:

string s;
string* _s = &s;
myfunc(_s);

잘 컴파일해야합니다.

그러나 이것은 함수에 전달하는 포인터를 수정하려는 경우에만 유용합니다. 문자열 자체를 수정하려면 Sake가 제안한대로 문자열에 대한 참조를 사용해야합니다. 이를 염두에두고 컴파일러가 원래 코드에 대해 불평하는 이유가 더 분명해야합니다. 코드에서 포인터는 '즉석에서'만들어 지므로 포인터를 수정해도 아무런 결과가 없으며 의도 한 것이 아닙니다. 참조 (포인터 대)의 아이디어는 참조가 항상 실제 객체를 가리키는 것입니다.


86

문제는 임시 참조를 참조에 바인딩하려고하는데 참조가 아닌 경우 C ++에서 허용하지 않습니다 const.

따라서 다음 중 하나를 수행 할 수 있습니다.

void myfunc(string*& val)
{
    // Do stuff to the string pointer
}


void myfunc2(string* const& val)
{
    // Do stuff to the string pointer
}

int main()
// sometime later 
{
    // ...
    string s;
    string* ps = &s;

    myfunc( ps);   // OK because ps is not a temporary
    myfunc2( &s);  // OK because the parameter is a const&
    // ...

    return 0;
}

Mr. Burr가 예를 들어 2 string* const& val와 같이 덜 읽기 쉬운 대신에 No.2의 방식을 작성하는 것이 특히 유익합니다 const string* &val. 내 눈에 이것은 분명히 const 참조 , 포인터, 문자열에 대한 것입니다. 나는 이 정확한 설명을 얻기 위해 선언 T const&대신 글을 쓰는 것을 선호합니다 const T&.
— fish2000

1
Nit pick (비평이 아님) : bind a temporary to the reference이 대답에서 @Chris 'as보다 문구 가 더 명확 reference to an actual string pointer in the calling scope, not an anonymous string pointer합니다. 어쨌든, 내 관점에서 둘 다 맞을 것입니다.
— kevinarpe

1
@ fish2000뿐만 아니라, const string*&그리고 string* const&실제로 다른 유형입니다. 첫 번째는 비이다 const(A)에 기준 const string*번째는 반면, const(A)에 대한 참조 string*.
— 저스틴 타임-복원 모니카

@ fish2000 은 @Justin Time이 지적한 바와 같이 "선호" T const&에 주의해야 const T&합니다. 때로는 결과가 없을 수도 있지만, 다른 상황에서는 선호하는 것보다 하나를 선호하는 것이 절대적으로 중요 int합니다 double.
— omatai

3
@ fish2000-하나는 "변경할 수없는 것으로 변경할 수있는 참조가 있습니다"라고 말하고 다른 하나는 "변경할 수없는 것으로 변경할 수없는 참조가 있습니다"라고 말합니다. 이 예제에서는 단순히 둘을 교환 할 수 없습니다.
— omatai

10

다음으로 변경하십시오.

  std::string s;
  std::string* pS = &s;
  myfunc(pS);

편집하다:

이것은 호출 ref-to-pointer되며 함수에 대한 참조로 임시 주소를 전달할 수 없습니다. (이 아닌 경우 const reference).

비록 std::string* pS = &s;(지역 변수에 대한 포인터)를 보여 주었지만, 일반적인 사용법은 다음과 같습니다. 피 호출자가 가리키는 객체가 아닌 포인터 자체를 변경하기를 원할 때. 예를 들어, 메모리를 할당하고 인수에 할당 된 메모리 블록의 주소를 할당하는 함수는 포인터 또는 포인터에 대한 포인터를 참조해야합니다.

void myfunc(string*& val)
{
//val is valid even after function call
   val = new std::string("Test");

}

5

&s 문자열에 대한 임시 포인터를 생성하고 임시 객체를 참조 할 수 없습니다.


4
이것은 사실이 아닙니다-const 임시 참조를 할 수 있습니다
— 1800 INFORMATION

3

시험:

void myfunc(string& val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(s);
    // ...
}

또는

void myfunc(string* val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(&s);
    // ...
}

그래도 내가하고있는 일에 대해서는 포인터 자체뿐만 아니라 포인터의 주소가 필요합니다. 값으로 포인터를 전달하고 싶지 않습니다.
— Alex

아직도 당신이 성취하려고하는 것을 이해하지 못합니다. "문자열 s"가 포인터가 아니기 때문에 "문자열 s"의 "포인터 주소"를 가질 수 없습니다.
— Sake

@ 알렉스 : 문자열이 내용이 같은지 여부가 아니라 저장하는 다른 문자열과 정확히 같은지 여부를 감지해야한다고 생각합니다. 이 경우 address-of 연산자를 참조에 사용할 수 있으며 참조 된 객체의 주소를 얻을 수 있습니다. void f (std :: string const & s) {std :: string const * p = & s; }
— David Rodríguez-dribeas

3

편집 : 나는 몇 가지를 실험하고 생각보다 조금 미묘한 것을 발견했습니다. 내가 지금 생각하는 것이 정답입니다.

&s는 lvalue가 아니므로 참조 유형이에 대한 참조가 아니면 참조를 작성할 수 없습니다 const. 예를 들어, 당신은 할 수 없습니다

string * &r = &s;

하지만 넌 할 수있어

string * const &r = &s;

함수 헤더에 비슷한 선언을 넣으면 작동합니다.

void myfunc(string * const &a) { ... }

또 다른 문제, 즉 임시 문제가 있습니다. 규칙은 임시 인 경우에만 참조를 얻을 수 있다는 것입니다 const. 따라서이 경우 & s는 일시적이라고 선언 할 수 있으므로 선언해야합니다.const 함수 프로토 타입에서 . 실제적인 관점에서이 경우에는 차이가 없습니다. (rvalue 또는 임시입니다. 어느 쪽이든 같은 규칙이 적용됩니다.) 그러나 엄밀히 말하면, 나는 그것이 일시적이 아니라 rvalue라고 생각합니다. 두 가지를 구별 할 수있는 방법이 있는지 궁금합니다. (아마도 모든 임시는 rvalue이고, 비 lvalue는 임시 인 것으로 정의되어 있습니다. 저는 표준 전문가가 아닙니다.)

즉, 귀하의 문제는 아마도 더 높은 수준 일 것입니다. 의 주소에 대한 참조를 원하는 이유는 무엇 s입니까? 에 대한 포인터를 참조하려면 다음과 같이 포인터 s를 정의해야합니다.

string *p = &s;
myfunc(p);

에 대한 참조 s또는 포인터를 원하면 s간단한 작업을 수행하십시오.


1

방금 루트 안전을 제외하고 삭제 된 이진 트리의 모든 포인터를 만들기 위해 포인터에 대한 참조를 사용했습니다. 포인터를 안전하게 만들려면 그냥 0으로 설정해야합니다. 루트 (이 포인터)를 첫 번째로 사용하고 있기 때문에 트리를 삭제하는 기능 (루트 만 유지)을 포인터에 대한 참조를 허용하는 함수를 만들 수 없습니다 왼쪽과 오른쪽을 통과하는 입력.

void BinTree::safe_tree(BinTree * &vertex ) {
    if ( vertex!=0 ) {  // base case
        safe_tree(vertex->left);    // left subtree.
            safe_tree(vertex->right);   //  right subtree.
          // delete vertex;  // using this delete causes an error, since they were deleted on the fly using inorder_LVR. If inorder_LVR does not perform delete to the nodes, then, use delete vertex;
        vertex=0;  // making a safe pointer
    }
} // end in

결론적으로, 공식 매개 변수가 (this) 포인터 인 경우 포인터에 대한 참조는 유효하지 않습니다.


1

C ++ 11 및 rvalue 참조에 오신 것을 환영합니다 :

#include <cassert>
#include <string>

using std::string;

void myfunc(string*&& val)
{
    assert(&val);
    assert(val);
    assert(val->c_str());
    // Do stuff to the string pointer
}

// sometime later 
int main () {
    // ...
    string s;
    myfunc(&s);
    // ...
}

이제 val문자열 주소 인 포인터 값 (에 의해 참조 됨 )에 액세스 할 수 있습니다 .

포인터를 수정할 수 있으며 아무도 신경 쓰지 않습니다. 이것이 rvalue가 무엇인지에 대한 한 측면입니다.

주의 : 포인터 값은 myfunc()반환 될 때까지만 유효 합니다. 마침내 일시적입니다.


-1

포인터의 참조를 전달하는 것이 가능하다는 것을 알고 있습니다. 지난주에했지만 코드가 내 뇌에 맞아 보이기 때문에 구문이 무엇인지 기억할 수 없습니다. 그러나 다른 옵션은 포인터의 포인터를 사용하는 것입니다.

Myfunc(String** s)

-8

myfunc ( "string * & val") 이것 자체는 의미가 없습니다. "string * & val"은 "string val"을 의미하며 *는 서로를 취소합니다. 마지막으로 문자열 변수를 함수 ( "string val")에 전달할 수 없습니다. 다른 데이터 유형은 포인터 또는 참조로 전달해야하므로 기본 데이터 유형 만 함수에 전달 될 수 있습니다. string & val 또는 string * val을 함수에 가질 수 있습니다.


4
모든 수준에서 잘못되었습니다. var 선언 구문을 새로 고치십시오.
— Ari
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.