Какова область этой строки?

Если у меня есть следующий код:

{
    UnicodeString sFish = L"FISH";
    char *szFish = AnsiString(sFish).c_str();

    CallFunc(szFish);
}

Тогда какова область действия временной созданной строки AnsiString и как долго szFish указывает на действительные данные? Будет ли он по-прежнему действителен для функции CallFunc?

Будет ли область видимости длиться всего одну строку или весь блок?

4 ответа

Решение

Стандарт C++11 $12.2.3 гласит:

Когда реализация вводит временный объект класса, который имеет нетривиальный конструктор (12.1, 12.8), он должен гарантировать, что конструктор вызывается для временного объекта. Точно так же деструктор должен быть вызван для временного с нетривиальным деструктором (12.4). Временные объекты уничтожаются как последний шаг в оценке полного выражения (1.9), которое (лексически) содержит точку, где они были созданы. Это верно, даже если эта оценка заканчивается выдачей исключения. Вычисления значений и побочные эффекты уничтожения временного объекта связаны только с полным выражением, а не с каким-либо конкретным подвыражением.

(акцент мой)

Есть дополнительные предостережения по этому поводу, но они не применяются в этой ситуации. В вашем случае полное выражение является указанной частью этого утверждения:

char *szFish = AnsiString(sFish).c_str();
//             ^^^^^^^^^^^^^^^^^^^^^^^^^

Итак, момент szFish назначен, деструктор вашего временного объекта (т.е. AnsiString(sFish)) будет вызываться и представление его внутренней памяти (где c_str() указывает на) будет выпущен. Таким образом, szFish будет немедленно становиться висящим указателем, и любой доступ потерпит неудачу.

Вы можете обойти это, сказав

CallFunc(AnsiString(sFish).c_str());

вместо этого, как здесь, временное будет уничтожено (снова) после полного выражения (то есть, прямо в ;) а также CallFunc сможет прочитать необработанную строку.

szFish недействителен перед звонком CallFunc(), так как AnsiString это временный объект, который разрушается немедленно и szFish указывает на свой внутренний буфер, который будет только что удален.

Убедитесь, что AnsiString Экземпляр действителен для вызова CallFunc(), Например:

CallFunc(AnsiString(sFish).c_str());

Я бы заменил:

char *szFish = AnsiString(sFish).c_str();

с:

AnsiString as(sFish);
char *szFish = as.c_str();

Я не знаю AnsiString класс, но в вашем коде его деструктор сработает до вашего вызова CallFunc()и, скорее всего, выпустит строку, на которую вы указываете *szFish, Когда вы заменяете временный объект на "именованный" объект в стеке, его время жизни увеличивается до конца блока, в котором он определен.

Область действия AnsiString в этом случае - "прямо перед вызовом c_str(), до сразу после". Это может помочь думать об этом так:

char *szFish; 

{ 
    AnsiString tmpString(sFish); 
    szFish = tmpString.c_str(); 
}
Другие вопросы по тегам