Но вопрос именно в какую область памяти копируется "Трям" что бы он не затирается по завершению функции?
Что-бы было понятнее Function1, на самом деле выглядит так (если перевести с языка ассембллера на C-подобный псевдокод):
static LPCWSTR tryamstr = L"Трям";
LPCWSTR Function1()
{
return tryamstr;
}
т.е. в первом случае L"Трям" никуда не копируется, а просто возвращается её адрес. Сама строка находится в секции данных, скорее всего в области доступной только для чтения.
Опять же вопрос 1 и 2 связаны, они обе куда то кладут "Трям" что он не затирается по завершению функции.
Во втором случае компилятор видит, что возвращается объект wstring и, выполняет перенос содержимого wstring s из внутреннего стека функции Fuction2, в переменную указанную в вызывающей функции. Т.е. на самом деле код выглядит примерно так:
static LPCWSTR tryamstr = L"Трям";
static wstring _temp;
void Function2()
{
wstring s = wstring(tryamstr);
_temp = s;
delete s;
return ;
}
void caller(void)
{
wstring rez;
Function2();
rez = _temp;
return ;
}
На самом деле двойного копирования (из s в _temp, а потом из _temp в rez) не происходит. При возврате из функции компилятор сам правильно указывает, как скопировать переменную на стеке wstring s в переменную вызывающей функции wstring rez. Более точно могут сказать знатоки C++.
И чем тогда функция 3 отличается от 2. Она тоже куда-то кладет строку, берет указатель на нее и должна бы вернуть, но ....
В третьем случае код выглядит, имхо, так:
static LPCWSTR tryamstr = L"Трям";
LPCWSTR Function3()
{
wstring s = wstring(tryamstr);
LPCWSTR _temp = s.c_str();
delete s;
return _temp;
}
В s хранится
КОПИЯ tryamstr, а не ссылка на неё. При вызове c_str() возвращается адрес
КОПИИ tryamstr, а при вызове delete s весь объект s, и копия tryamstr внутри него уничтожаются и получается, что _temp, который возвращается вызывающей функции, указывает на уже освобождённую область памяти.