문제

예전에는 C++를 많이 사용하지 않았고 최근에는 C#을 많이 사용하고 있는데 다시 C++의 기본으로 돌아가는 데 정말 어려움을 겪고 있습니다.작업상 가장 편리한 C++ 구문을 사용할 수 없으므로 이는 특히 까다롭습니다. 따라서 모든 문자열은 char *여야 하고 STL 목록에 대한 규정은 없습니다.

현재 제가 하려는 작업은 문자열 목록을 만드는 것입니다. STL이나 C#을 사용하면 시간이 전혀 걸리지 않습니다.기본적으로 다음과 같은 기능을 갖고 싶습니다.

char **registeredNames = new char*[numberOfNames];

그 다음에,

RegisterName(const * char const name, const int length)
{
    //loop to see if name already registered snipped
    if(notFound)
    {
        registeredNames[lastIndex++] = name;
    }

}

아니면 C#이었다면...

if(!registeredNames.Contains(name))
{
    registeredNames.Add(name);
}

그리고 나는 그것이 작동하지 않는다는 것을 깨닫습니다.나는 전달된 변수(const 포인터와 const 문자열)의 const 특성이 다소 어렵다는 것을 알고 있지만, 내 기본적인 문제는 과거에 STL 목록 등을 사용하여 항상 이러한 상황을 피해왔다는 것입니다.그래서 나는 그 문제를 해결할 필요가 없었습니다!

도움이 되었습니까?

해결책

문자열이 이미 저장되어 있는지 확인하려면 strcmp를 사용해야 할 수도 있습니다.

for (int index=0; index<=lastIndex; index++)
{
  if (strcmp(registeredNames[index], name) == 0)
  {
    return; // Already registered
  }
}

그런 다음 실제로 문자열 복사본을 저장해야 하는 경우 버퍼를 할당하고 문자를 복사해야 합니다.

char* nameCopy = malloc(length+1);
strcpy(nameCopy, name);
registeredNames[lastIndex++] = nameCopy;

입력이 NULL로 끝나는지 여부를 언급하지 않았습니다. 그렇지 않은 경우 추가 주의가 필요하며 strcmp/strcpy는 적합하지 않습니다.

다른 팁

STL을 피할 수 있는 타당한 이유가 있습니다.메모리나 속도가 중요한 고정된 환경에서 작업할 때 STL을 사용하여 내부에서 무슨 일이 일어나고 있는지 파악하기 어려울 때가 있습니다.예, 자체 메모리 할당자를 작성할 수 있습니다. 예, 일반적으로 속도는 문제가 되지 않습니다. 하지만 플랫폼 전반에 걸쳐 STL 구현 간에는 차이가 있으며 이러한 차이는 미묘하고 잠재적으로 버그가 있을 수 있습니다.메모리는 아마도 사용을 고려할 때 가장 큰 관심사일 것입니다.

메모리는 소중하며 이를 사용하는 방법을 엄격하게 제어해야 합니다.이 길을 따라가본 적이 없다면 이 개념이 이해되지 않을 수도 있지만 이는 사실입니다.도구(게임 코드 외부)에서는 STL 사용을 허용하지만 실제 게임 내부에서는 금지됩니다.또 다른 관련 문제는 코드 크기입니다.STL이 실행 파일 크기에 얼마나 기여할 수 있는지는 약간 확신할 수 없지만 STL을 사용할 때 코드 크기가 눈에 띄게 증가하는 것을 확인했습니다.실행 파일이 "단" 2M 더 크다고 해도 게임의 다른 항목에 대한 RAM은 2M 더 적은 것입니다.

STL은 확실히 좋습니다.하지만 자신이 무엇을 하고 있는지 모르는 프로그래머가 이를 남용할 수 있습니다.의도적인 것은 아니지만 보고 싶지 않을 때 불쾌한 놀라움을 제공할 수 있습니다(다시 말하지만 메모리 팽창 및 성능 문제).

나는 당신이 당신의 솔루션에 가깝다고 확신합니다.

for ( i = 0; i < lastIndex; i++ ) {
    if ( !strcmp(&registeredNames[i], name ) {
        break;    // name was found
    }
}
if ( i == lastIndex ) {
    // name was not found in the registeredNames list
    registeredNames[lastIndex++] = strdup(name);
}

strdup을 사용하고 싶지 않을 수도 있습니다.이는 주어진 예에서 이름을 저장하는 방법에 대한 단순한 예입니다.새 이름을 위한 공간을 직접 할당하지 않거나 앱에서 이미 사용 가능한 다른 메모리 구성을 사용하고 싶을 수도 있습니다.

그리고 제발 문자열 클래스를 작성하지 마세요.나는 문자열 클래스를 C++에서 기본 C 구성을 리엔지니어링하지 않는 방법에 대한 최악의 예로 꼽았습니다.예, 문자열 클래스는 멋진 세부 정보를 많이 숨길 수 있지만 메모리 사용 패턴이 형편없고 콘솔에 잘 맞지 않습니다(예:ps3 또는 360 등) 환경.약 8년 전에도 우리는 같은 일을 했습니다.메인 메뉴에 도달하기 전에 200000개 이상의 메모리 할당이 필요합니다.메모리가 심하게 조각화되어 게임의 나머지 부분을 고정된 환경에 맞출 수 없었습니다.우리는 그것을 찢어 버렸습니다.

클래스 디자인은 어떤 면에서는 훌륭하지만 이것은 그 중 하나가 아닙니다.이것은 의견이지만 실제 경험을 바탕으로 한 것입니다.

이식성이 문제라면 확인해 보세요. STL포트.

STL을 사용할 수 없는 이유는 무엇입니까?

어쨌든 간단한 문자열 클래스와 목록 템플릿을 직접 구현하는 것이 좋습니다.이렇게 하면 평소와 동일한 기술을 사용하고 포인터와 메모리 관리를 해당 클래스에만 국한시킬 수 있습니다.STL을 흉내낸다면 더욱 좋을 것 같습니다.

정말로 stl을 사용할 수 없다면(그리고 제가 게임 산업에 종사할 때 그렇게 믿었던 것이 후회됩니다) 자신만의 문자열 클래스를 만들 수 없나요?가장 기본적인 문자열 클래스는 생성 및 할당 시 메모리를 할당하고 소멸자에서 삭제를 처리합니다.나중에 필요에 따라 추가 기능을 추가할 수 있습니다.완전히 이식 가능하며 작성 및 단위 테스트가 매우 쉽습니다.

char*를 사용하려면 C 함수를 사용해야 합니다.귀하의 경우 실제로 필요한 것은 문자열을 복사하는 것입니다.당신을 돕기 위해 strndup 기능이 있습니다.그런 다음 다음과 같이 작성해야 합니다.

void RegisterName(const char* name)
{
  // loop to see if name already registered snipped
  if(notFound)
  {
    registerNames[lastIndex++] = stdndup(name, MAX_STRING_LENGTH);
  }
}

이 코드에서는 배열이 충분히 크다고 가정합니다.

물론 가장 좋은 것은 자신만의 문자열과 배열, 목록을 적절하게 구현하는 것입니다.또는 상사에게 STL이 더 이상 사악하지 않다고 확신시키려면!

편집하다:제가 귀하의 질문을 오해한 것 같습니다.내가 알고 있는 이 코드에는 상수성 문제가 없습니다.

나는 머리 속에서 이것을 하고 있지만 거의 옳을 것입니다:

static int lastIndex = 0;
static char **registeredNames = new char*[numberOfNames];

void RegisterName(const * char const name)
{
    bool found = false;
    //loop to see if name already registered snipped
    for (int i = 0; i < lastIndex; i++)
    {
        if (strcmp(name, registeredNames[i] == 0))
        {
            found = true;
            break;
        }
    }

    if (!found)
    {
        registeredNames[lastIndex++] = name;
    }
}

STL을 사용할 수 없는 이유를 이해할 수 있습니다. 대부분의 경우 코드가 엄청나게 부풀어 오릅니다.그러나 게임 프로그래머에 의한 게임 프로그래머를 위한 구현이 있습니다. RDESTL 그런 도서관 중 하나입니다.

사용:

const char **registeredNames = new const char * [numberOfNames];

을(를) 할당할 수 있습니다. const * char const 배열의 요소에.

단지 궁금해서, 왜 "작업에서는 가장 편리한 C++ 구문을 사용할 수 없도록 규정"합니까?

제안된 모든 접근 방식은 유효합니다. 제 요점은 C#이 수행하는 방식이 이를 복제하는 것이 매력적이라면 자신만의 클래스/인터페이스를 만들어 동일한 추상화를 제공한다는 것입니다.Contains 및 Add 메서드가 있는 간단한 연결 목록 클래스, 다른 답변에서 제공하는 샘플 코드를 사용하면 비교적 간단합니다.

C++의 가장 큰 장점 중 하나는 일반적으로 원하는 방식으로 모양과 동작을 만들 수 있다는 것입니다. 다른 언어에 일반적으로 재현할 수 있는 기능이 훌륭하게 구현되어 있는 경우에도 가능합니다.

나는 이 String 클래스를 수년간 사용해 왔습니다.

http://www.robertnz.net/string.htm

STL 문자열의 모든 기능을 제공하지만 템플릿이 아닌 진정한 클래스로 구현되며 STL을 사용하지 않습니다.

이것은 당신이 스스로 굴릴 수 있는 분명한 사례입니다.벡터 클래스에도 동일한 작업을 수행합니다.

  • 테스트 우선 프로그래밍으로 수행하십시오.
  • 간단하게 유지하세요.

MT 환경에서는 문자열 버퍼의 참조 계산을 피하세요.

규칙에 대해 걱정하지 않고 작업을 완료하려면 realloc을 사용하십시오.나는 항상 목록에 대해 이런 종류의 작업을 수행합니다. 다음과 같습니다.

T** list = 0;
unsigned int length = 0;

T* AddItem(T Item)
{
 list = realloc(list, sizeof(T)*(length+1));
 if(!list) return 0;
 list[length] = new T(Item);
 ++length;
 return list[length];
}

void CleanupList()
{
 for(unsigned int i = 0; i < length; ++i)
 {
  delete item[i];
 }
 free(list)
}

더 많은 일을 할 수 있습니다.목록 크기가 두 배가 될 때마다 realloc만 수행, 인덱스별로 목록에서 항목을 제거하거나 동일성을 확인하는 기능, 목록 처리를 위한 템플릿 클래스 만들기 등...(오래 전에 쓴 것이 있는데 항상 직접 사용하고 있어요...하지만 안타깝게도 저는 직장에 있어서 여기에 복사해서 붙여넣을 수는 없습니다.)솔직히 말해서 이것은 STL에 상응하는 성능을 능가하지는 못할 것입니다. 하지만 많은 작업을 수행하거나 특히 STL 구현이 좋지 않은 경우에는 성능이 동일할 수 있습니다.

짜증나게도 C++에는 realloc을 대체하기 위한 갱신/크기 조정 연산자가 없습니다. 이는 매우 유용할 것입니다.

아, 그리고 내 코드에 오류가 있으면 사과드립니다. 방금 메모리에서 꺼냈습니다.

const 정확성은 STL 사용 여부에 관계없이 여전히 const 정확성입니다.나는 당신이 찾고 있는 것이 등록된 이름을 다음과 같이 만드는 것이라고 믿습니다. const char ** 그래서 임무는 registeredNames[i] (이것은 const char *) 작동합니다.

게다가, 이것이 정말로 당신이 하고 싶은 일인가요?문자열의 복사본을 만드는 것이 더 적절할 것 같습니다.

더욱이, 수행 중인 작업을 고려하여 이것을 목록에 저장하는 것에 대해 생각해서는 안 됩니다. 세트가 더 좋을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top