C++에서 문자열의 일부를 리턴하는 방법 문의
글쓴이: parkon / 작성시간: 수, 2015/08/19 - 11:44오전
안녕하세요,
문자열을 리턴 할 때마다 자신도 없고 골치도 아프군요.
예를 들어 80개의 char를 가지는 문자열 char fStrData[80+1]
이
global 변수로 지정되어 있다고 할때요,
이 문자열의 처음 10자와 20칸부터 두자를 합한 문자열을 리턴하는 함수를 만드려고 합니다.
const char* foo() { char* s1= new char[12+1]; strncpy(s1, fStrData, 10); strncat(s1, fStrData+20, 2); return s1; }
이런식으로 하면 잘 돌아가긴 할 것 같은데
new를 쓰니 속도면에서도 불리해 보이고, 또 반한된 s1을 나중에 free해 줘야 하는 부담때문에
이렇게는 쓰고 싶지 않습니다.
const char* foo() { char s2[12+1]; strncpy(s2, fStrData, 10); strncat(s2, fStrData+20, 2); return s2; }
이런 식으로 하니 컴파일러나 환경에 따라 잘 되기도 하고 쓰레기 값이 나오기도
하고 그러더군요.
아마 s2가 휘발성이 있는 stack 변수여서 그렇겠지요,
저는 CERN의 ROOT라는 툴의 TString을 사용하는 데 아마 MSDN의 CString하고
문법이 거의 같을 거예요.
그럼
const char* foo() { TString s(fStrData, 10); s.Append(fStrData+20, 2); return s.Data(); }
이런 식으로 해도 문제가 발생하려나요 ?
문자열을 반환하는 좋은 해답 알려주시면 감사하겠습니다.
Forums:
1. new 에는 delete(free
1. new 에는 delete(free 아니여요)
2. 지역변수의 주소는 절대로 리턴하면 안됩니다.
3. 저라면 전형적인 C 함수 인터페이스를 사용할 것 같네요.
답변 감사합니다. 특히 전형적인 c함수 인터페이스가
답변 감사합니다.
특히 전형적인 c함수 인터페이스가 안전하긴 하겠군요.
...
1. Profile을 떠보기 전에 "이 부분이 느릴 것 같아요" 하는 것은 삽질로 이어질 확률이 대단히 높습니다. 다시 말해, 프로그램을 다 짠 다음 프로파일러를 돌려서 실제로 new/delete에서 시간을 많이 소모하는 걸 확인하기 전까지는 거기서 시간이 많이 걸릴지 걱정할 필요가 없습니다. 그때 가서 걱정하세요.
new/delete는 생각하는 것보다 빠릅니다. 제 컴퓨터에서 테스트해 보니 초당 500만개쯤 쉽게 만들었다 지웠다 하네요.
2. C++을 쓰신다면 특별한 사정이 없는 한 std::string을 사용하시는 걸 추천합니다.
500만개도 금방 되는군요, 답변 감사합니다.
500만개도 금방 되는군요, 답변 감사합니다.
의견
1. 꼭 TString이라는 것을 사용하지 않고 두 번째 예제처럼 작성해도 된다면,
정적 변수를 이용하는 것도 괜찮은 답이라고 생각합니다.
C++이니 std::string을 이용하는 것도 가능한데 이 경우는 고려하지 않으셨나요?
예제 코드입니다.
저는 이렇게 생각했습니다.
보여주신 foo2의 std::string의
보여주신 foo2의 std::string의 substr을 사용하는 마지막 예는
stack 변수의 휘발성 문제가 없는 건가요 ?
그렇다면 꽤나 매력적인 해법으로 보입니다.
아 그러고 보니 return형을 const
아 그러고 보니 return형을
const char*가 아니라 string으로 해서
그 로컬 변수의 휘발성 문제를 해결하신 것으로 보이는 군요.
답변
네. C++에서는 스택에 생성한 객체를 반환할 때
반환할 객체를 임시 객체에 복사해서 반환합니다.
그래서 멤버에 포인터 변수가 있는 경우 주의해야 하는데 이 경우와는 관계없는 이야기고,
std::string에 대해서는 휘발성 문제가 없습니다.
저는 이렇게 생각했습니다.
덧붙이자면 함수 내 정적변수를 이용한 구현은
덧붙이자면 함수 내 정적변수를 이용한 구현은 thread 안전성이 없습니다.
(단, 해당 정적변수가 상수라면 상관없습니다. 너무 당연한건가;)
multi-thread라면 이러한 구현은 지양하시구요.
single thread라면 좋은 해법이 될 듯 합니다.
최근에 bluez 라이브러리 뜯어보고 있었는데, hciconfig이었나? hcitool 이었나
single thread라 위와 비슷한 구현이 눈에 띄더군요.
(보통 지역변수조차 스택에 올리는 시간 아끼려고하는 건지
전역변수 / 지역 정적변수로 대체하더군요.)
답변 감사드립니다. 이리 저리 여러 해법이 있는건
답변 감사드립니다.
이리 저리 여러 해법이 있는건 알겠는데 딱 맘에 드는 게 없는게 문제네요.
(이건 현재 제 이해가 짧아서 생기는 현상이겠지만 말이죠)
현재 (ROOT에만 있는 녀석인지 몰라도) Form이라는 함수를 써서 코딩했고,
나중 문제가 생기면 정적 변수로 전환할까 생각하고 있습니다.
멀티 스레드라면 thread_local 변수를 이용할
멀티 스레드라면 thread_local 변수를 이용할 수 있습니다.
클래스의 객체에 대해서 stack 변수의 휘발성
클래스의 객체에 대해서 stack 변수의 휘발성 운운하시는 걸로봐서는 C++을 공부한 적이 없으신 것같습니다.
C++은 생긴게 C같다고해서 C하던 사람이 C++공부안하고 쓸수있는 언어가 아닙니다.
먼저 C++입문서와 활용서를 한두권 정도 정독하시고 도전하시는걸 추천합니다.
-
-댓글 위치 이동
댓글 달기