Локальные переменные создаются на «стек», которые имеют срок службы сферы они существуют в в частности, то, что происходит в вашем оригинальном футляре:.
string data="Mustafa Hi";
const char* cptr=data.c_str();
return cptr;
осложняется тем фактом, чтоstst :: string - это объект с деструктором. До C++ 11, возможно, он сохранил строку без завершающего нуля, если вы не вызвали c_str(). Внутри он содержит указатель и значение размера, а также значение емкости. Он выделяет память для хранения строки. Подумайте (пре-C++ 11) станд :: строку, как это:
class String {
char* m_ptr;
size_t m_length;
size_t m_alloc;
public:
String() : m_ptr(nullptr), m_length(0), m_alloc(0) {}
String(const char* src) {
size_t length = strlen(src);
m_ptr = new char[length];
m_alloc = m_length;
memcpy(m_ptr, src, length); // not including the \0
}
const char* c_str() {
if (m_length == 0)
return nullptr;
if (m_alloc > m_length) // we're null terminated
return m_ptr;
char* newPtr = new char[length + 1];
memcpy(m_ptr, newPtr, length);
delete [] m_ptr;
m_ptr = newPtr;
m_ptr[length] = '\0';
++m_alloc;
return m_ptr;
}
~String() {
#ifdef _DEBUG
if (m_ptr) m_ptr[0] = 0;
#endif
delete [] m_ptr;
}
};
Ваша функция принимает адрес экземпляра этого объекта, а затем возвращая этот адрес. Следующее, что происходит, это то, что экземпляр выходит из области действия и вызывает его деструктор - он был в стеке и сразу после вашего кода, поэтому местоположение стека, в котором он находилось, теперь доступно для использования любым кодом, который вызывается следующим.
Взгляните на следующий пример (демо: http://ideone.com/wAcY3B)
#include <iostream>
int* getInt1(int input)
{
int i = input;
std::cout << "created 'i' at " << (void*)&i << std::endl;
int* ptr1 = &i;
return ptr1;
}
int* getInt2(int input)
{
int* ptr3 = new int(input);
return ptr3;
}
int main()
{
int i = 0;
std::cout << "i is on the stack, it's address is " << (void*)&i << std::endl;
int* ip = new int(1);
std::cout << "ip is on the heap, it's address is " << (void*)ip << std::endl;
int* p1 = NULL;
int* p2 = NULL;
int* p3 = NULL;
// force the pointers to be assigned locations on the stack by printing them.
std::cout << "created p1(" << &p1 << "), p2(" << &p2 << ") and p3(" << &p3 << ")" << std::endl;
p1 = getInt1(10101);
std::cout << "p1(" << &p1 << ") = " << (void*)p1 << " -> " << *p1 << std::endl;
p2 = getInt1(20202);
std::cout << "p2(" << &p2 << ") = " << (void*)p2 << " -> " << *p2 << std::endl;
// but more importantly
std::cout << "p1(" << &p1 << ") = " << (void*)p1 << " -> " << *p1 << std::endl;
p3 = getInt2(30303);
std::cout << "p3(" << &p3 << ") = " << (void*)p3 << " -> " << *p3 << std::endl;
std::cout << "p2(" << &p2 << ") = " << (void*)p2 << " -> " << *p2 << std::endl;
std::cout << "p1(" << &p1 << ") = " << (void*)p1 << " -> " << *p1 << std::endl;
}
Выход выглядит следующим образом:
i is on the stack, it's address is 0xbfb49a90
ip is on the heap, it's address is 0x9b83008
created p1(0xbfb49a94), p2(0xbfb49a98) and p3(0xbfb49a9c)
created 'i' at 0xbfb49a6c
p1(0xbfb49a94) = 0xbfb49a6c -> 10101
created 'i' at 0xbfb49a6c
p2(0xbfb49a98) = 0xbfb49a6c -> 20202
p1(0xbfb49a94) = 0xbfb49a6c -> -1078682988
p3(0xbfb49a9c) = 0x9b83018 -> 30303
p2(0xbfb49a98) = 0xbfb49a6c -> -1078682988
p1(0xbfb49a94) = 0xbfb49a6c -> -1078682988
Поскольку указатель стека не изменяется между вызовами «getInt1 () «локальные переменные экземпляры находятся в одном месте, но если вы вызываете некоторые другие случайные функции между назначениями, они будут использовать одно и то же расположение стека, и ваши заостренные значения будут потеряны.
В дополнение к ответам, вероятно, вы должны просто вернуть объект 'string', а не' const char * '(если у вас нет * очень * веских причин). – syam
Правда, я знаю, что не буду использовать его. Я просто пытаюсь понять. –
Что касается вашего редактирования ('int *' case), вы не делаете то же самое: вы создаете новый 'int' в куче, который выживает в области функции (в отличие от вашего случая' string', где строка находится в стеке и уничтожается при выходе из функции). Однако во втором случае у вас есть утечка памяти, потому что вы никогда не удаляете 'int'. – syam