Как, имея std::string, вызвать конструктор, принимающий char*?
Имеется конструктор:
// Конструктор
Marshrut4D (char * val1)
: vecBasePoints(),
vecPoints4D(),
currentPos(BasePoints4D(EMPTY_DEF,EMPTY_DEF,EMPTY_DEF,EMPTY_DEF,EMPTY_DEF,0,'\0',12))
{
nameType[0] = '\0';
if (val1 != nullptr)
strcpy(name,val1);
else
name[0] = '\0';
}
На вход просит, как видно, char*. Но есть одна переменная которая имеет не тип char[32] (большая часть имён в проекте имеет тип char[32], но есть несколько std::string), а std::string. Как поступить в таком случае? Возможно ли как-то вызвать этот конструктор ? (с помощью преобразований std::string).
Попробовал использовать c_str(). Столкнулся теперь с такой проблемой: метод getName возвращает std::string. Результат работы первых двух стейтментов такой какой нужно, в конечном итоге sd1 указывает на нужную строку, но если заменить первые два стейтмента на третий, то в sdd у меня "\0". Имена переменных сделал от балды, пожалуйста, не обращайте на это внимание. Всё это тесты для того, что бы понять что и как работает.
void ContMarshrut4D::addNewMarshrut(PlanFor4D * uplan)
{
std::string sdfs = uplan->getName();
const char* sd1 = sdfs.c_str(); //sd1 нужная строка
const char* sdd = (uplan->getName()).c_str(); //а тут в sdd "\0"
}
Собственно, подытожу вопрос: почему при выполнении
const char* sdd = (uplan->getName()).c_str();
результат != результату
std::string sdfs = uplan->getName();
const char* sd1 = sdfs.c_str(); //sd1 нужная строка
//-----------тут метод getName---------
class PlanFor4D
{
public:
PlanFor4D() : traek_(),
track_(),
name_("\0"),
nameType_("\0")
{
}
~PlanFor4D() {}
void createPlanFromKST(P4_POLETA_NBT * p4_poleta_nbt, char * name);
std::string getName() { return name_; }
std::string getNameType() { return nameType_; }
PlanFor4D * getPlan() { PlanFor4D * ptr = this; return ptr; }
private:
std::vector<BasePoints4D> traek_;
std::vector<BasePoints4D> track_;
std::string name_; // Номер борта ВС
std::string nameType_; // Тип ВС
friend void Marshrut4D::setBasePoints(PlanFor4D * uplan);
};
Ответы (1 шт):
Ваша функция std::string getName() { return name_; } возвращает копию строки. И после точки с запятой в строке
const char* sdd = (uplan->getName()).c_str();
это временный объект уничтожается. И sdd начинает указывать куда то в дебри памяти. Обращение по такому удаленному указателю - UB и оно может приводить к чему угодно (хотя иногда оно даже и работает:) - это законно при UB. Но чаще всего падает в разных, иногда странных, местах).
Когда Вы используете вот так
std::string sdfs = uplan->getName();
const char* sd1 = sdfs.c_str(); //sd1 нужная строка
то копия строки сохраняется в sdfs и живет до конца блока видимости (он же scope). Обычно это до парной закрывающей фигурной скобки. И в этом случае sd1 указывает на рабочую память внутри sdfs.
Что такого в c_str? это функция, которая должна возвращать указатель на си строку. У нее есть по факту два варианта - просто возвратить указатель на внутренний буфер, который будет очищен в деструкторе (обычно так и делается), или создать новый буфер и вернуть указатель на него. Но тогда кто будет очищать память? И такой метод не используется в с++, хотя достаточно часто встречается в разных движках от игр (может называться GetCopyOfBuffer - где то такое видел)
Как пофиксить Ваш код максимально просто? Возвращайте не копию строки, а ссылку на константу.
const std::string& getName() const { return name_; }
и теперь все Ваши варианты будут работать - ведь c_str теперь будет возвращать буфер, который хранит name_. Правда, когда родительский класс PlanFor4D будет уничтожен, то и указатель испортиться. Но скорее всего у Вас этого пока не случится. Ещё один плюс этого метода - не создаются лишние копии.