Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
mariko_11
2 / 2 / 1
Регистрация: 11.03.2013
Сообщений: 64
#1

Сколько живёт строковый литерал? - C++

06.02.2014, 18:00. Просмотров 1044. Ответов 26
Метки нет (Все метки)

Имеется код
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
using namespace std;
 
class myClass
{
public:
    myClass(char *s){str=s;}
    void print() {cout << str << endl;}
 
private:
    char *str;
};
 
int main()
{
    myClass a("ne erunda li?");
 
    a.print();
 
    cout << "Hello World!" << endl;
    return 0;
}
Сколько живёт строковый литерал? Не будет ли такой проблемы, что после выходе из конструктора в память, где ранее хранилось "ne erunda li?\0", будет записано что-то ещё?

Кстати, компилятор выдаёт предупреждение с указанием на строчку, где объявляется объект:
C:\Users\Students\Documents\untitled8\main.cpp:17: предупреждение: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
myClass a("ne erunda li?");
^
Как можно это обойти с минимальными изменениями кода класса?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.02.2014, 18:00     Сколько живёт строковый литерал?
Посмотрите здесь:

Строковый литерал - C++
Вопрос к профи: Верно ли что, когда мы инициализирум строку вот так: const char *str = &quot;Строка&quot;, то компилятор понимает ее так: 1) char...

Как в макросе передать параметр в строковый литерал? - C++
Как в макросе передать параметр в строковый литерал? #define f(s) &quot;left##s##right&quot; не работает. Т.к. по команде cout &lt;&lt;...

Строковый литерал и указатель на строку. В чем разница? - C++
Добрый день. Начал только изучать С++, не могу понять в чем разница между указателем на литерал и указателем на строку??? Заранее...

Как правильно возвращать строковый литерал из функции - C++
Строковый литерал по сути представляет собой указатель на данные. Но что если литерал был создан внутри функции и его значение вернуть?...

Локальный указатель на локальный строковый литерал - C++
Здравствуйте. Подскажите, пожалуйста, почему локальный указатель, созданный в функции, не уничтожается после вызова функции? То есть мы...

Передать литерал функции - C++
Когда я создаю объект string, я могу написать так: string str = &quot;qwerty&quot;; // или string str(&quot;qwerty&quot;); // не суть //...

Что такое широкий литерал? - C++
Что такое широкий литерал? Объясните новичку. Совсем недавно решил изучать C++ по книге

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
7060 / 4201 / 949
Регистрация: 30.01.2014
Сообщений: 6,968
06.02.2014, 22:44     Сколько живёт строковый литерал? #16
Цитата Сообщение от mariko_11 Посмотреть сообщение
Таки знаю, что нельзя. То есть, везде примеры с динамическим выделением памяти и копированием литерала в изменяемую строку, потому что может потребоваться её менять? Именно из-за этого не используется вариант с const char *?
И поэтому тоже. А в том примере, на который заругались, был strcpy в невыделенную память, что есть UB.
Вот так нельзя, потому что p это только указатель, а не строка, в данном случае он даже ни на что не указывает. Попытка проведения этой операции скорее всего закончится крахом программы. Поэтому человек и заменил этот пример, на тот, где память выделяется, соответственно и копирование становится возможным.
C++
1
2
char * p;
strcpy(p, "test");
DrARTI
0 / 1 / 0
Регистрация: 25.04.2013
Сообщений: 6
06.02.2014, 22:45     Сколько живёт строковый литерал? #17
Цитата Сообщение от Black Fregat Посмотреть сообщение
Или проставить в классе const
C++
1
2
3
4
5
6
7
8
9
class myClass
{
public:
    myClass(char const *s){str=s;}
    void print() {cout << str << endl;}
 
private:
    char const *str;
};
>>myClass(char const *s){str=s;}
Ну идея-то, конечно, верная, но есть рациональный вопрос: а зачем? То есть, например, чисто на практике, как это вообще сможет пригодиться?
ОП, вопрос у тебя изначально странный очень. На то литерал и литерал, чтобы быть константой (ну т.е. относительно бессмертным), нет? Ну а если ты делаешь его копию в виде переменной (про ссылку на константу пока молчу), то, очевидно, время жизни этой копии уже будет независимо от времени жизни литерала?
DrOffset
7060 / 4201 / 949
Регистрация: 30.01.2014
Сообщений: 6,968
06.02.2014, 22:58     Сколько живёт строковый литерал? #18
Цитата Сообщение от DrARTI Посмотреть сообщение
>>myClass(char const *s){str=s;}
Ну идея-то, конечно, верная, но есть рациональный вопрос: а зачем? То есть, например, чисто на практике, как это вообще сможет пригодиться?
Запросто может пригодиться (немного не в таком виде, но схожем), для оптимизации например. Вот пример.
Сам использовал похожий класс в большом проекте для представления подстрок. Помогло избежать оверхеда по выделению памяти и копированию строк. Но граничные условия разумеется надо знать, подход не везде применим.
mariko_11
2 / 2 / 1
Регистрация: 11.03.2013
Сообщений: 64
06.02.2014, 23:03  [ТС]     Сколько живёт строковый литерал? #19
Цитата Сообщение от DrOffset Посмотреть сообщение
И поэтому тоже. А в том примере, на который заругались, был strcpy в невыделенную память, что есть UB.
Вот так нельзя, потому что p это только указатель, а не строка, в данном случае он даже ни на что не указывает. Попытка проведения этой операции скорее всего закончится крахом программы. Поэтому человек и заменил этот пример, на тот, где память выделяется, соответственно и копирование становится возможным.
C++
1
2
char * p;
strcpy(p, "test");
Да не, я про то, что ругались на вариант с const. Что в невыделенную память нехорошо копировать, я в курсе.
DrARTI
0 / 1 / 0
Регистрация: 25.04.2013
Сообщений: 6
06.02.2014, 23:05     Сколько живёт строковый литерал? #20
Цитата Сообщение от DrOffset Посмотреть сообщение
Запросто может пригодиться (немного не в таком виде, но схожем), для оптимизации например. Вот пример.
Сам использовал похожий класс в большом проекте для представления подстрок. Помогло избежать оверхеда по выделению памяти и копированию строк. Но граничные условия разумеется надо знать, подход не везде применим.
Я, конечно, очень люблю, когда мне отвечают, но тут слишком многобукафф. Может, получится по-конкретнее немного? Кусок кода там, или синопсис какой-нибудь, не знаю. Я ведь со своим знанием плюсов не пойму иначе ничерта.
DrOffset
7060 / 4201 / 949
Регистрация: 30.01.2014
Сообщений: 6,968
06.02.2014, 23:28     Сколько живёт строковый литерал? #21
Цитата Сообщение от DrARTI Посмотреть сообщение
Я, конечно, очень люблю, когда мне отвечают, но тут слишком многобукафф. Может, получится по-конкретнее немного? Кусок кода там, или синопсис какой-нибудь, не знаю. Я ведь со своим знанием плюсов не пойму иначе ничерта.
Я просто привел ссылку на один из самых авторитетных источников, чтобы не было сомнений в том, что я говорю
Можно концепцию проиллюстрировать:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class string_view
{
public:
    typedef char const *   iterator;
    typedef const iterator const_iterator;
 
    string_view(char const * str, size_t len);
    string_view(const_iterator begin, const_iterator end);
    string_view();
 
    const_iterator begin() const;
    const_iterator end() const;
 
    size_t size() const; 
 
    string_view substr(size_t start, size_t len = -1) const;
 
private:
    char const * begin_;
    char const * end_;
};
Представим, что у нас есть некий большой буфер, содержащий строку, которую надо парсить на подстроки. Так как нам нужно данные только читать, то такое решение идеально подойдет. В отличие от обычной строки тут нет расходов на копирование и выделение памяти для подстрок. Каждая подстрока просто "вырезанное" представление части более общей строки.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char buf[size] = "very long string for parsing";
 
some_parsing_algo(string_view(buf, size));
//.....
 
void some_parsing_algo(string_view const & str)
{
// все STL алгоритмы с итераторами будут работать
// найдем первый пробел
    string_view::const_iterator space = std::find(str.begin(), str.end(), ' ');
    if(space != str.end())
    {
         // получим подстроку "very"
         string_view sub = str.substr(0, std::distance(str.begin(), space));
    }
}
Реализация методов string_view тривиальна.
Естественно тут нужно следить за временем жизни буфера, который используется в таком представлении.
DrARTI
0 / 1 / 0
Регистрация: 25.04.2013
Сообщений: 6
07.02.2014, 00:37     Сколько живёт строковый литерал? #22
DrOffset, очень интересный код, благодарствую!

Добавлено через 15 минут
Сохранил даже, будет полезно в роли примера.
Ilot
Модератор
Эксперт С++
1807 / 1164 / 226
Регистрация: 16.05.2013
Сообщений: 3,060
Записей в блоге: 5
Завершенные тесты: 1
07.02.2014, 11:21     Сколько живёт строковый литерал? #23
Цитата Сообщение от DrOffset Посмотреть сообщение
Тоже не очень, обретем проблемы с копированием и последующим двойным удалением. Лучший вариант именно такого подхода - внутри держать std::string какой-нибудь. Либо запретить копирование вообще. Либо реализовать одну из семантик передачи владения.
Смотрим на эту строчку:
C++
1
    myClass(const myClass&);
Объявление конструктора копирования без его определения это и есть запрет копирования.
Croessmah
Модератор
Эксперт CЭксперт С++
13058 / 7321 / 817
Регистрация: 27.09.2012
Сообщений: 18,071
Записей в блоге: 3
Завершенные тесты: 1
07.02.2014, 12:33     Сколько живёт строковый литерал? #24
Цитата Сообщение от Ilot Посмотреть сообщение
это и есть запрет копирования.
который сработает только на стадии линковки...
DrOffset
7060 / 4201 / 949
Регистрация: 30.01.2014
Сообщений: 6,968
07.02.2014, 13:43     Сколько живёт строковый литерал? #25
Цитата Сообщение от Ilot Посмотреть сообщение
Смотрим на эту строчку:
C++
1
    myClass(const myClass&);
Объявление конструктора копирования без его определения это и есть запрет копирования.
Запретом копирования это было бы будь оно в привате. Либо, в рамках нового стандарта объявлено как
C++
1
myClass(const myClass&) = delete;
Ilot
Модератор
Эксперт С++
1807 / 1164 / 226
Регистрация: 16.05.2013
Сообщений: 3,060
Записей в блоге: 5
Завершенные тесты: 1
07.02.2014, 14:02     Сколько живёт строковый литерал? #26
DrOffset, тогда попрбуйте скомпилировать такой код:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A{
    int a;
public:
    A(int a1): a(a1)
    {}
    A(const A&);
};
int main()
{
    A obj1(11);
    A obj2 = obj1;
 
    return 0;
}

Croessmah, как бы мысль понял. А как это проверить на стадии выполнения программы? Не совсем понимаю. Пусть даже компилятор пропустит код без определения конструктора все равно во время выполнения программы произойдет обращение к несуществующей функции и по идее программа должна "слететь". Так? Т.е. другими словами копирования объектов все-равно не произойдет?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.02.2014, 14:12     Сколько живёт строковый литерал?
Еще ссылки по теме:

Литерал - что делать с указателем? - C++
Недавно увидел нечто подобное. Раньше считал, что литерал может быть преобразован только в char - т.е. храниться на стеке, а там уже в...

Строквой литерал в двоичном представлении - C++
Добрый день. В учебнике есть задание: составить пользовательский тип который может вместить значение факториала числа 1000 с абсолютной...

Литерал это значение любой переменой, ведь так ? - C++
Добрый вечер. По ходу изучения программирования скопилось немало вопросов, к которым периодически приходится возвращаться. Поэтому...

Какое получается значение и тип имеет литерал 3.14e1L - C++
3.14e1L Какое получается значение и тип? смущает суффикс e

Строковый анализатор - C++
Подскажите почему код выдает всякий мусор, подает звуковые сигналы Должен работать так: Если введешь так: &quot;11/23/34&quot; или &quot;11.23.34&quot;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
DrOffset
7060 / 4201 / 949
Регистрация: 30.01.2014
Сообщений: 6,968
07.02.2014, 14:12     Сколько живёт строковый литерал? #27
Цитата Сообщение от Ilot Посмотреть сообщение
DrOffset, тогда попрбуйте скомпилировать такой код:
Croessmah, как бы мысль понял.
Кажется с его стороны это был сарказм. Код, который вы дали приводит к unresolved external во время линковки. Croessmah и я вам как бы намекали, что это слишком поздно и неплохо бы это отловить еще на этапе компиляции! Для этого сейчас в новом стандарте есть стандартное средство.

Цитата Сообщение от Ilot Посмотреть сообщение
А как это проверить на стадии выполнения программы? Не совсем понимаю. Пусть даже компилятор пропустит код без определения конструктора все равно во время выполнения программы произойдет обращение к несуществующей функции и по идее программа должна "слететь". Так? Т.е. другими словами копирования объектов все-равно не произойдет?
Не нужно проверять на этапе выполнения Прочитайте еще раз пожалуйста мое предыдущее сообщение. Чтобы запретитькопирование с диагностикой на этапе компиляции в С++98 и С++03 конструктор копирования помещают в приват без реализации. См. например boost::noncopyable. В С++11 для запрещения каких либо операций с классом ввели стандартное средство, которое я демонстрировал
Yandex
Объявления
07.02.2014, 14:12     Сколько живёт строковый литерал?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru