Указатели на строковые литералы остаются допустимыми после того, как функция возвратится?

Когда вы видите исключение ItemsSource doesn't support CollectionViewSource, вы можете отсортировать коллекцию по Linq, прежде чем передать ее в DataGrid:

ObservableCollection<MyDataClass> myCollection = new ObservableCollection<MyDataClass>();
dataGrid.ItemsSource = from item in myCollection orderby item select item;

Необходимо реализовать интерфейс IComparable для MyDataClass:

public class MyDataClass : IComparable<MyDataClass> {
    public int CompareTo(Classified other) {
        return other.Value.CompareTo(this.Value); // DESC
        return this.Value.CompareTo(other.Value); // ASC
    }
}
17
задан Rob Kennedy 19 October 2009 в 16:22
поделиться

4 ответа

Продолжительность хранения:

2.13.4 Обычные строковые литералы и строковые литералы UTF-8 также называются узкими строковыми литералами. Стрелка строковый литерал имеет тип «массив из n const char», где n - размер строки, как определено ниже, и имеет продолжительность статического хранения

, считываемая совместно с 3.7.1

3.7.1.

Все объекты, которые не имеют продолжительности динамического хранения, не имеют продолжительности хранения потока и являются не локальные имеют статическую продолжительность хранения. Хранение этих предметов должно длиться в течение всего срока хранения. программа (3.6.2, 3.6.3).

Тип:

Приложение C

Подпункт 2.13.4:

Изменение : Строковые литералы сделаны const Тип строкового литерала изменяется с «массив символов» на «массив константных символов». Типа Строковый литерал char16_t изменяется с «массив некоторого целого типа» на «массив констант char16_t». В тип строкового литерала char32_t изменен с «массив некоторого целого типа» на «массив констант char32_- т. " Тип широкого строкового литерала изменяется с «array of wchar_t» на «array of const wchar_t».

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

Влияние на исходную функцию: Изменение семантики четко определенной функции. Сложность преобразования: простое синтаксическое преобразование, поскольку строковые литералы можно преобразовать в char *; (4.2). Наиболее распространенные случаи обрабатываются новым, но устаревшим стандартным преобразованием: char * p = "abc"; // допустимо в C, не рекомендуется в C ++ char * q = expr? «abc»: «de»; // допустимо в C, недопустимо в C ++

Насколько широко используется: Программы, у которых есть законные основания рассматривать строковые литералы как указатели на потенциально модифицируемая память, вероятно, встречается редко.

Динамически выделяемая (слово «куча» никогда не используется в контексте области памяти AFAIK в стандарте) память требует вызова функции, которая может произойти уже в main намного позже выделения статической памяти.

25
ответ дан 30 November 2019 в 10:27
поделиться

Этот код полностью действителен и соответствует требованиям. Единственная проблема - убедиться, что вызывающий абонент не пытается освободить строку.

13
ответ дан 30 November 2019 в 10:27
поделиться

Этот код действителен и соответствует стандартам.

Строковые литералы хранятся в постоянной памяти, а функция просто получает адрес выбранной строки.

Стандарт C ++ (2.13.4) гласит:

Обычный строковый литерал имеет тип «Массив из n const char» и статический продолжительность хранения

Ключ к пониманию вашей проблемы - это статическая продолжительность хранения: строковые литералы выделяются при запуске вашей программы и сохраняются на протяжении всей программы. Ваша функция просто получает адрес и возвращает его.

12
ответ дан 30 November 2019 в 10:27
поделиться

Технически да, это действительно так.
У строк есть статическая длительность хранения.

Но это еще не все.

Это C-строки. Соглашение в C-библиотеках и функциях - возвращать динамически выделяемую строку, которая должна быть освобождена. т.е. возвращенный указатель неявно передает право собственности обратно вызывающей стороне (как обычно в C, есть также исключения).

Если вы не будете следовать этим соглашениям, вы запутаете многих опытных разработчиков C, которые ожидали этого соглашения. Если вы не следуете этим стандартным ожиданиям, тогда это должно быть хорошо задокументировано в коде.

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

Если вы беспокоитесь об эффективности, я думаю, что это ложная проблема.

Если вы хотите, чтобы это было для печати через потоки, для этого уже существует стандартное соглашение:

std::cout << std::boolalpha << false << std::endl;
std::cout << std::boolalpha << true  << std::endl;
5
ответ дан 30 November 2019 в 10:27
поделиться
Другие вопросы по тегам:

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