2010-04-01 2 views
4

아래 코드를 참조하십시오. 이 코드에서는 참조로 test.c_str()에 의해 반환 된 const char*을 저장하고 있습니다. 제 질문은 - datatest의 내용을 올바르게 참조합니까? 나는 test.c_str()에 의해 반환 된 ptr이 임시로 될 것이라고 생각하고 있는데, 참조에 바인딩하면 유효하지 않을 것입니다.임시로 참조에 포인터 바인딩하기

내 생각이 맞습니까? StoringClass이

class StoringClass 
{ 
    const char*& data; 
public: 
    StoringClass (const char*& input): data(input) 
    { 
    } 
} 

EDIT1: 은 그냥 수 std 무엇을 : : 문자열이하고있는 생각하지 말자입니다

class RefPtrTest 
{ 
    std::string test; 
    StoringClass storingClass; 
public: 
    RefPtrTest(): test("hello"), storingClass(test.c_str()) 
    { 
    } 
} 

. 내가

class RefPtrTest 
{ 
    const mystring test; 
    StoringClass storingClass; 
public: 
    RefPtrTest(): test("hello"), storingClass(test.getInternalPointer()) 
    { 
    } 
} 

getInternalPointer 직접 내부 포인터를 반환을 mystring에라는 내 자신의 클래스를 사용하고 가정하자. 나는이 가설을 검증하기를 원한다. test.getInternalPointer()에 의해 반환 된 ptr은 일시적 일 것이고 나는 그것을 참조로 묶는다면 유효하지 않을 것이다. 내 생각이 맞습니까?

EDIT2: StoringClass가 내 통제하에 있지 않습니다. 기본적으로 템플릿 클래스는 형식에 대한 참조를 저장합니다. const char*에 사용 중입니다. 나는 당신이 제기 한 모든 디자인 문제를 알고 있습니다. 하지만 그 클래스를 변경할 수는 없으므로 const char *에 사용해야합니다. 그 주위에는 다른 방법이 없습니다.

+0

왜 포인터 복사본 대신 포인터에 대한 참조를 저장하려고하는지 알 수 없습니다. – pmr

답변

1

StoringClass에 포인터에 대한 참조가 필요한 경우 참조의 길이만큼 수명이있는 참조 포인터 (const 참조가 아니기 때문에 수정해야 함)가 있어야합니다. . :

#include <string> 
#include <iostream> 

template <typename T> 
class StoringClass { 
    T& data; 
public: 
    StoringClass (T& input): data(input) { } 
    void print() const { std::cout << data << "\n"; } 
    void set(T x) { data = x; } 
}; 

class RefPtrTest { 
    const std::string test; 
    const char *ptr; 
    StoringClass<const char*> storingClass; 
public: 
    RefPtrTest(): test("hello"), ptr(test.c_str()), storingClass(ptr) { } 
    void print() const { storingClass.print(); } 
    void set(const char* x) { storingClass.set(x); } 
}; 

int main() { 
    RefPtrTest t; 
    t.print(); 
    t.set("world"); 
    t.print(); 
} 

출력 :

hello 
world 

IMO StoringClass 조금 이상한 것입니다. 예를 들어 set 기능도 const으로 표시 할 수 있으며 여전히 작동합니다. 그러나 그것을 사용해야하는 경우, 그것을 사용해야합니다. StoringClass<const char *const>을 대신 사용할 수 있다면 포인터를 수정하는 StoringClass의 기능을 호출하지 않도록하는 것이 좋습니다. 당신이 질문 한 방식은 당신이 그 일이 일어날 것이라고 기대하지 않는다는 것을 암시합니다.

편집 :

void set_another_way(const char *x) { test = x; set(test.c_str()); } 

storingClass가 참조하는 포인터를 문자열을 수정하고 업데이트 할 것입니다 :에서 const되지 않은

test 경우,하지만, RefPtrTest 함수를 가질 수있다. 함수 본문은 test = x; ptr = test.c_str();과 같습니다. 단일 스레드 코드를 가정 할 경우 test.c_str()에 의해 반환 된 포인터 값의 유효성에 대한 모든 문제를 해결합니다 (단 set_another_waytest이 수정되는 유일한 방법 임).

솔직히 StoringClassStoringClass이라고해서는 안됩니다. 아무 것도 저장하지 않습니다 .-p

+0

RAII 의미론을 부여 했으므로이 문제를 해결하기 위해 똑같은 작업을했습니다 (다른'const char *'를 사용하여). –

3

test.c_str()이 실제로 포인터에 대한 참조를 반환하지 않는 한 생각은 정확합니다 (test.c_str()은 임시를 반환하므로 참조를 초기화 할 수 없습니다) ... 그거야?

하지만이 방법을 사용하면 컴파일 오류가 발생합니다.

이 특별한 경우 실제로 포인터를 사용하면 많은 의미가 없습니다. 그러나 포인터에 대한 참조 만 요구하면 형식에 관계없이 올바른 것입니다. 프로그램은 어레이에 저장된 임의의 값을 변경하지 한다

+1

test.c_str()는 포인터를 반환하고, test는'std :: string'입니다. –

+0

std :: string :: c_str()이 포인터에 대한 참조를 반환하는지 확실하지 않았습니다. – falstro

+0

@roe'const' 임시 변수에 대한 참조는 합법입니다. http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry (이 특별한 경우에는 참조가 사용되지 않지만). –

3

표준 약 c_str (21.3.6/2)

은 말할 필요에 다음을 갖는다. 객체를 객체로 지정하는 basic_string 클래스의 비 const 멤버 함수에 대한 이후의 호출 이후에 반환 값을 유효한 포인터로 처리하지 않아야합니다.

따라서 대답은 아니오입니다. 포인터를 문자열의 내용에 대한 참조로 처리 할 수 ​​없습니다 (문자열에 대한 const가 아닌 함수 호출 이후).

+0

괜찮 았어, 난 비 const 멤버 함수를 호출하지 오전. 나는 그것을 너무 바꾸고 싶지 않다. const char *을 필요로하는'StoringClass'를 사용하고 있기 때문에 이것을 사용하고 있습니다.이 문자열을 한 번만 생성합니다. –

+0

@Yogesh Arora'const char * & data'를'const char * data'로 변경해야합니다 –

+1

@ Yogesh : 당신이하고 싶은 모든 일이 유효하다면, 무엇을 먼저 참조해야합니까? – UncleBens

-1

유효 할 수도 있습니다. 그러나이 동작에 의존해서는 안됩니다.

string 클래스 구현은 char* 아래에 있고 c_str() 메서드는 해당 배열의 시작 부분으로 포인터를 반환합니다.그러나 시간이 지남에 따라 문자열이 변경되면이 내부 배열이 메모리에서 이동하고 크기가 변경 될 수 있습니다. stringchar*으로 전환 할 때마다 c_str()을 호출해야합니다.

아마도 포인터가 내부 메모리에 반환되므로 어쨌든 매우 빠릅니다.

+1

여기서 관련성을 보지 못했습니다. 포인터에 대한 참조를 말하는 것입니까? 포인터가 의미가 있는지 여부가 아닙니다. – falstro

+0

@roe '제 질문은 데이터가 정확하게 테스트 내용을 참조 할 것입니까? – pajton

1

문자열 버퍼를 직접 수정하면 안됩니다.

일반적으로 포인터를 처리 할 때 포인터 유형이 갖는 주소를 변경하려면 포인터에 대한 참조 만 필요합니다. 버퍼를 변경하기 만하면 char *를 간단히 저장할 수 있습니다.

이 사용하는 표준처럼 버퍼를 액세스 할 수 : 벡터를 대신 같은 뭔가하려면 다음

std::vector<char> v; 
v.resize(size); 
strcpy(&v.front(), "testing"); 
1

cplusplus.com에서 표준 : : 문자열 c_str() 멤버 함수에 대한 다음 설명을 참조하십시오

반환되는 배열은이 문자 시퀀스와 끝나는 null 문자에 필요한 저장 공간이있는 내부 위치를 가리 킵니다. 그러나이 배열의 값은 프로그램에서 수정되어서는 안되며 변경되지 않고 유지되어야합니다 다음 전화가 올 때까지 문자열 객체의 상수가 아닌 멤버 함수

게시 한 코드에 const가 아닌 멤버 함수를 호출하지는 않지만 매우 좋은 생각입니다. RefPtrTest 클래스에서 개인 std :: sting 테스트 변수를 수정하면 실수로 StoringClass 클래스에 영향을 미치게됩니다 (이는 RefPtrTest의 캡슐화에 위배됩니다). 누군가 당신의 코드를 나중에 (아마도 당신이) 깨닫지 못할 수도 있고 버그/충돌을 소개 할 수도 있습니다.