Символ константы копии*

Я получаю струну до в качестве параметра от функции, но аргумент, который я получаю, будет уничтоженным позже. Таким образом, я хочу сделать копию из него.

Вот то, что я имею в виду:

class MyClass
{
private:
 const char *filename;

public:
 void func (const char *_filename);
}

void MyClass::func (const char *_filename)
{
 filename = _filename; //This isn't going to work
}

То, чего я хочу достигнуть, не, просто присваивают один адрес памяти другому, но скопировать содержание. Я хочу иметь имя файла как "символ константы*" и не как "символ*".

Я пытался использовать strcpy, но он требует, чтобы целевая строка была неконстантой.

Вокруг существует ли путь? Что-то, не используя const_cast на имени файла?

Спасибо.

12
задан Ilya Suzdalnitski 18 February 2010 в 10:10
поделиться

8 ответов

Используйте std :: string , чтобы скопировать значение, поскольку вы уже используете C ++. Если вам нужен const char * из этого, используйте c_str () .

class MyClass
{
private:
    std::string filename;
public:
    void setFilename(const char *source)
    {
        filename = std::string(source);
    }

    const char *getRawFileName() const
    {
        return filename.c_str();
    }
}
26
ответ дан 2 December 2019 в 04:02
поделиться

char const * подразумевает, что класс не владеет связанной с ним памятью. Владельцу всегда нужен неконстантный указатель, потому что в противном случае память не может быть освобождена. Если у вас есть неконстантный указатель, вы можете выделить для него память, а затем использовать strcpy (или memcpy ) для копирования самой строки. Однако в вашей ситуации использование std :: string является гораздо лучшим вариантом.

-1
ответ дан 2 December 2019 в 04:02
поделиться

Вы должны решить, хотите ли вы, чтобы имя вашего файла было константным (чтобы его нельзя было изменить) или неконстантным (чтобы его можно было изменить в MyClass :: func).

2
ответ дан 2 December 2019 в 04:02
поделиться

В стандартной библиотеке C есть функция (если вы хотите пойти по маршруту C) под названием _strdup. Он использует malloc для фактического распределения, поэтому вам нужно будет вызвать free, когда вы закончите со строкой.

Так, например,

void MyClass::func (const char *_filename)
{
    if (filename)
    {
        free(filename);
    }
    filename = _strdup(_filename);
}

Конечно, не забудьте освободить имя файла в деструкторе.

2
ответ дан 2 December 2019 в 04:02
поделиться

[Предполагая, что вы продолжаете реализовывать внутренние компоненты своего класса в стиле C, что может быть или не быть полезным с точки зрения скорости разработки и выполнения (в зависимости от дизайна всего проекта), но обычно не рекомендуется в пользу std :: string и друзья.]

Превращение

const char *filename;

в

char *filename;

не сделает вас счастливыми с strcpy , поскольку вам действительно нужна память для копии вашей строки :)

Относительно части кода ручного управления памятью см. Ответ Тадеуша Копека, который, кажется, все в порядке.

Также имейте в виду, что существует разница между

const char *filename; // "filename" points to "const char" 
                      //  and is not const itself
char const *filename; // semantically the same as above

и

char * const filename; // "filename" is const and points to "char", 
                       //  which is not const

. В первом случае вы можете указать filename на любую другую строку const char , во втором вы можете изменить эту строку только «на месте» (так, чтобы значение filename оставалось неизменным, поскольку оно указывает на то же место в памяти). Конечно, при необходимости можно комбинировать эти два (или ни один из них).

P.S. Если вы назвали параметр своей функции-члена _filename только для того, чтобы избежать конфликта имен с переменной-членом filename , вы можете просто префикс this (и избавиться от подчеркивание):

void MyClass::func (const char *filename)
{
 ...
 this.filename = copy;
}
1
ответ дан 2 December 2019 в 04:02
поделиться

Почему у вас это как const, если вам нужно изменить их в одном из методов класса.

В любом случае нестатическим константным элементам данных и ссылочным элементам данных нельзя присвоить значения; вы должны использовать список инициализации с конструктором для их инициализации.

MyClass::MyClass(const char *_filename) : filename( _filename ) 
{ 
   // filename = _filename; This isn't going to work 
}

Инициализатор также может вызывать функцию, как показано ниже.

MyClass::MyClass(const char *_filename) : filename( getfilename() ) 
{ 
   // filename = _filename; This isn't going to work 
}

Не проверял этот конкретный случай, который является подходящим, но список инициализации - это способ присвоения значений нестатическим константным элементам данных.

0
ответ дан 2 December 2019 в 04:02
поделиться

Если вы хотите придерживаться обычного C, используйте strncpy. Но я согласен с Ильей, используйте std::string, так как это уже C++. Если это ваше приложение вызывает ваш метод, вы можете даже получить std::string в первую очередь, так как исходный аргумент будет уничтожен.

0
ответ дан 2 December 2019 в 04:02
поделиться

Я согласен, что лучше всего (по крайней мере, не зная ничего больше о вашей проблеме) использовать std::string. Но если вы настаиваете на самостоятельном управлении памятью, то вы должны управлять ею полностью. Итак, путь C++:

class MyClass
{
private:
 const char *filename;

 MyClass(const MyClass&); // no implementation
 MyClass operator=(const MyClass &); // no implementation

public:
 MyClass() {filename = 0;}
 ~MyClass() {delete[] filename;}

 void func (const char *_filename);
}

void MyClass::func (const char *_filename)
{
 const size_t len = strlen(_filename);
 char * tmp_filename = new char[len + 1];
 strncpy(tmp_filename, _filename, len);
 tmp_filename[len] = '\0'; // I'm paranoid, maybe someone has changed something in _filename :-)
 delete[] filename;
 filename = tmp_filename;
}

и путь C

class MyClass
{
private:
 const char *filename;

 MyClass(const MyClass&); // no implementation
 MyClass operator=(const MyClass &); // no implementation

public:
 MyClass() {filename = 0;}
 ~MyClass() {free(filename);}

 void func (const char *_filename);
}

void MyClass::func (const char *_filename)
{
 free(filename);
 filename = strdup(_filename); // easier than C++, isn't it?
}
7
ответ дан 2 December 2019 в 04:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: