2017-01-19 16 views
-1

Мы можем хранить строку, используя 2 метода.Что является более эффективным способом хранения строк, массива или указателя в C/C++?

Метод 1: с помощью массива

char a[]="str"; 

Способ 2:

char *b="str"; 

В методе 1 памяти используется только в хранении строку "ул", так что память используется 4 байта.

В методе 2 память используется при сохранении строки «str» в «Read-Only-Memory», а затем при хранении указателя на 1-й символ строки. Таким образом, используемая память должна быть 4 байта для хранения строки в ПЗУ, а затем 8 байтов для хранения указателя (в 64-разрядной машине) до первого символа.

Всего 1-й метод использует 4 байта, а метод 2 использует 12 байтов. Точно так же метод 1 всегда лучше, чем метод 2 для хранения строк в C/C++.

+0

В методе one 'a' по-прежнему является указателем на данные« str », только с некоторым синтаксическим сахаром. –

+0

И почему вы думаете, что 'a' не занимает никакой памяти в методе 1? Что на ваш взгляд? – PeterK

+0

нет * «ROM» * внутри вашего компьютера ... – specializt

ответ

1

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

Вам нужно больше заботиться о Неопределенное поведение во втором случае!

char a[] = "str"; 

правильно объявляет нон массив символов, который константный инициализируется в "str". Это означает, что a[0] = 'S'; вполне разрешено и будет изменять a до "Str".

Но с

char *b = "str"; 

вы объявляете нон константный указатель на litteral массив символов, который является неявным Уст. Это означает, что b[0] = 'S'; пытается изменить литровую строку и является Undefined Behavior => он может работать, segfault или что-то среднее между ними, включая не меняя строку.

0

Все номера, которые вы указываете, и тип памяти, в которой хранится строковый литерал, зависят от платформы.

Что является более эффективным способом для хранения строк, массив или указатель

Некоторые педантизм о терминологии: Указатель не может хранить строку; он сохраняет адрес. Строка всегда хранится в массиве, и указатель может указывать на нее. Строковые литералы, в частности, хранятся в массиве статической продолжительности хранения.

Способ 1: использование массива char a[]="str";

Это делает копию содержимого строкового литерала в локальный массив продолжительности автоматического хранения.

Метод 2: char *b="str";

Вы не можете связать нон указатель константный к строкового литерала в стандартном C++. Это плохо сформировано на этом языке (начиная с C++ 11, до этого конверсия была просто устаревшей). Даже в C (и расширениях C++), где это преобразование разрешено, это довольно опасно, поскольку вы можете случайно передать указатель на функцию, которая может попытаться изменить указанную строку. Корректность верности заменяет случайный UB ошибкой времени компиляции.

Игнорируя это, это не делает копию литерала, но указывает на него.

Таким образом, метод 1 всегда лучше метода 2 для хранения строк в C/C++.

Использование памяти - не единственная метрика, которая имеет значение. Метод 1 требует копирования строки из литерала в автоматический массив. Не делать копии обычно быстрее, чем делать копии. Это становится все более важным со все более длинными строками.

Основное отличие метода 1 и 2 состоит в том, что вы можете изменить локальный массив метода 1, но вы не можете изменять строковые литералы. Если вам нужен модифицируемый буфер, то метод 2 не дает вам этого - независимо от его эффективности.

0

Дополнительные соображения:

Предположим, что ваша система не является RAM компьютер на базе ПК, а компьютер с истинной энергонезависимой памяти (NVM), такие как микроконтроллер. Строковый литерал "str" затем в обоих случаях будет храниться в NVM.

В случае массива строковый литерал должен быть скопирован из NVM во время выполнения, тогда как в случае с указателем вам не нужно делать копию, вы можете просто указать прямо на строковый литерал.

Это также означает, что в таких системах, предполагая 32 бит, версия массива будет занимать 4 байта ОЗУ для массива, а версия указателя будет занимать 4 байта ОЗУ для указателя. Оба случая должны будут занять 4 байта NVM для строкового литерала.

+0

И если моя система - это ноутбук, который является 64-битной машиной, то версия массива будет занимать 4 байта ОЗУ, а указатель займет 8 байт ОЗУ, и оба они будут занимать 4 байта NVM. Правильно ли я понял? – user1825567

+0

@ user1825567 Возможно, хотя C не гарантирует, что 'int' равно 4 байтам, или что указатель имеет 8 байтов. Также обратите внимание, что на таком компьютере с разрешением 8GB RAM ваш 8-байтовый указатель занимает приблизительно 0,000000000097% от общей ОЗУ. Это означает, что пространство памяти, занимаемое этим указателем, вероятно, является наименее важной вещью, о которой вам нужно беспокоиться. – Lundin

+0

Я получаю вашу мысль. Но я не ищу практических ответов, просто теоретический ответ, действительно ли это дело на бумаге. Итак, что вы думаете, если я действительно обеспокоен моим ресурсом? – user1825567

 Смежные вопросы

  • Нет связанных вопросов^_^