визуальная студия 2008 sp1 std::string::c_str() ошибка

я встретил такую ​​​​же ситуацию в моем проекте.
Аналогичным образом был воспроизведен следующий код.

#include <iostream>
#include <vector>
using namespace std;


class METHOD
{
public:
vector<METHOD*> m_arg;
string name;
string getName()
{
    return name;
}
METHOD()
{

}
METHOD(string n)
{
    name = n;
}
};

class PF : public METHOD
{
public:
PF(){};
};

void main()
{


PF p;
p.m_arg.push_back(new METHOD(string("a")));
p.m_arg.push_back(new METHOD(string("b")));
p.m_arg.push_back(new METHOD(string("c")));

for(int i = 0 ; i < (int)p.m_arg.size() ; ++i)
{
    const char* ccs = p.m_arg[i]->getName().c_str();  //PROBLEM POINT

    size_t ss = strlen(ccs);
}

}

проблема в том, что //ПРОБЛЕМА
адрес возврата c_str() не может быть назначен const char* ccs.
в отладчике css назначает адрес памяти для возврата c_str(), но значение css равно "" и работает так же, как ""

но следующий код работает как положено.

    string str("ok");
const char* ckk = str.c_str();

после этого кода ckk указывает после того, как str.c_str() возвращает адрес, а значение ckk в отладчике равно "ok"

та же проблема возникает в std::wstring, wchar_t, unicode.

почему возникла эта проблема?
кто знает? помогите мне плз~

ДОБАВИТЬ: благодаря mystical я решаю проблему так же. но это решение также работает нормально.

    for(int i = 0 ; i < (int)p.m_arg.size() ; ++i)
{
    string& strr = p.m_arg[i]->getName();
    const char* ccs = strr.c_str();
    size_t ss = strlen(ccs);
}

поэтому я думаю, что возвращаемое значение getName() остается в силе до закрытия цикла}.
но что интересно, следующее не работает

    for(int i = 0 ; i < (int)p.m_arg.size() ; ++i)
{
    string* strr = &p.m_arg[i]->getName();
    const char* ccs = strr->c_str();
    size_t ss = strlen(ccs);
}

css "болтается", а также strr ""
я ошеломлен и сбит с толку!


person user1006322    schedule 31.10.2011    source источник


Ответы (1)


В вашей функции getName():

string getName()
{
    return name;
}

Возвращаемая строка является копией оригинала. Он становится промежуточным в следующем выражении:

const char* ccs = p.m_arg[i]->getName().c_str();

Когда выражение заканчивается, это промежуточное звено уничтожается. Поэтому аннулирование указателя, возвращаемого c_str(). В результате ccs становится оборванным указателем.

Причина, по которой это работает:

string str("ok");
const char* ckk = str.c_str();

потому что str не является промежуточным звеном.

Чтобы это сработало, измените цикл следующим образом:

for(int i = 0 ; i < (int)p.m_arg.size() ; ++i)
{
    string str = p.m_arg[i]->getName()
    const char* ccs = str.c_str();

    size_t ss = strlen(ccs);
}

EDIT: чтобы ответить на ваш новый вопрос:

Причина, по которой это не работает:

string* strr = &p.m_arg[i]->getName();

такой же, как и раньше. getName() возвращает промежуточное значение. Затем вы берете этот адрес и назначаете его strr. Промежуточное значение уничтожается после оператора, поэтому strr становится висячим указателем, как и в первом случае.

person Mysticial    schedule 31.10.2011
comment
Другое исправление состоит в том, чтобы getName() возвращала std::string const& (и сама функция тоже должна быть const). Тогда выражение допустимо, и задействованная строка не копируется. - person Mat; 31.10.2011
comment
Вы также можете пойти дальше и встроить его в файл strlen. Но цикл явно неполный, так как ss никогда не используется. - person Mysticial; 31.10.2011
comment
strlen тоже весьма сомнительно; std::string::size() - это O (1), а не O (n). - person MSalters; 31.10.2011