Комментарии, вероятно, приведут вас в заблуждение или в лучшем случае запутают вас. Позвольте мне разбить его на несколько вариантов.
Во-первых, проблема в том, что вы говорите: массив, адрес которого вы возвращаете, больше не существует, когда функция извлекается из стека для вызывающей стороны. Игнорирование этого результата в Undefined Behavior.
Вызывающая сторона владеет буфером
void readFromFlashMemory(char *s, size_t len)
Преимущество заключается в том, что вызывающая сторона выбирает, как распределяется эта память, что полезно во встроенных средах.
Обратите внимание, что вы также можете выбрать s
для этой функции для удобства или для передачи некоторого дополнительного значения.
Для меня, если бы я работал во встроенной среде, такой как Arduino, это было бы моим предпочтением 100%.
Использование std::string
, std::vector
или подобное
std::string readFromFlashMemory()
Вероятно, именно так вы и поступили бы, если бы вас не волновали накладные расходы и другие потенциальные проблемы, такие как фрагментация во времени.
Выделите память самостоятельно
char* readFromFlashMemory()
Если вы хотите убедиться, что выделенная память точно соответствует размеру, то вы, вероятно, сначала прочитаете в локальный буфер, а затем выделите память и скопируете. Те же аспекты памяти, что и std::string
или другие решения, связанные с кучей памяти.
Эта форма также имеет свойство nightmari sh вызывающей стороны, которая отвечает за управление возвращаемым указателем и, в конечном итоге, вызывает delete[]
. Это крайне нежелательно. Это также печально распространено. : (
Лучший способ вернуть динамически выделенную память, если вам абсолютно необходимо
std::unique_ptr<char[]> readFromFlashMemory()
То же, что # 3, но указатель управляется безопасно. Требуется C + +11 или более поздняя версия.
Использование буфера stati c
const char* readFromFlashMemory()
{
static char s[FLASH_STOP_ADDR-FLASH_START_ADDR+2];
// ...
return s;
}
Обычно вызывает недовольство. Особенно потому, что этот тип шаблона приводит к неприятным проблемам в многопоточные среды.
Люди в основном выбирают этот подход, потому что они ленивы и хотят простой интерфейс. Я предполагаю, что одним из преимуществ является то, что вызывающей стороне не нужно ничего знать о том, какой размер буфера приемлем.
Создайте свой собственный класс с внутренним буфером
class FlashReader
{
public:
const char* Read();
private:
char buffer[FLASH_STOP_ADDR-FLASH_START_ADDR+2];
};
Это более подробное решение, которое может пахнуть как чрезмерное инженерство. Но оно сочетает в себе лучшее части как # 1, так и № 5. То есть, вы получаете выделение стека вашего буфера, вам не нужно знать размер, а сама функция не нуждается в дополнительных аргументах.
Если вы сделал хочу иметь ati c buffer, тогда вы можете просто определить один экземпляр класса * stati c, но различие было бы ясным намерением этого в коде.