Как вернуть массив символов, созданный в функции? - PullRequest
12 голосов
/ 17 сентября 2010

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

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

Некоторое время я не замечал этого, потому что массивы символов при выводе на консоль не выглядели поврежденными (возможно, потому, что не было времени перезаписать эти данные). Однако я заметил это, когда возвращал строковый буфер (массив символов), сгенерированный чтением последовательного порта, который часто был поврежден.

Итак, как лучше мне это сделать?

Мой плохой код выглядит следующим образом:

#include <cstdlib>
#include <iostream>

using namespace std;

char* myBadFunction(){
    char charArray[] = "Some string\n";
    char* charPointer = charArray;
    return charPointer;
}


int main(int argc, char** argv) {

    cout << myBadFunction();

    return 0;
}

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

Следующий код также не делает то, что я хочу, чтобы он правильно:

#include <cstdlib>
#include <iostream>

using namespace std;

void fillArray(char* charPointer){
    char charArray[] = "Some string\n"; // Create string
    charPointer = charArray; // Not correct, want to fill predefined array with created string
    return;
}


int main(int argc, char** argv) {

    char predefinedArray[50] = {0};
    fillArray(predefinedArray);
    cout << predefinedArray;

    return 0;
}

Я хочу заполнить массив, на который указывает проанализированный указатель, но в коде выше этого не происходит.

Кроме того, когда мне следует использовать команду new [] для создания массива? это нужно? и когда я должен вызвать delete [] на нем.

Большое спасибо за это, это, очевидно, очень фундаментально, но что-то, что я делал некоторое время неправильно.

Ответы [ 4 ]

10 голосов
/ 17 сентября 2010

Самый простой способ - вернуть std::string, а если вам нужен доступ к внутреннему массиву символов, используйте std::string::c_str().

#include <iostream>
#include <string>

using namespace std;

string myGoodFunction(){
    char charArray[] = "Some string\n";
    return string(charArray);
}


int main(int argc, char** argv) {  
    cout << myGoodFunction();
    return 0;
}

Если вам нужно вернуть что-то, кроме массива char, помните, что указатели могут использоваться в качестве итераторов. Это позволяет вам инкапсулировать массив в вектор или подобную структуру:

vector<int> returnInts() {
    int someNums[] = { 1, 2, 3, 4 };
    return vector<int>(someNums, someNums + 4);
}
6 голосов
/ 17 сентября 2010

У вас есть два варианта возврата массива в C ++. Вы можете заполнить предварительно выделенную память (хорошо) или выделить свою собственную внутри функции и вернуть ее (плохо). Причина, по которой первый вариант предпочтительнее, заключается в том, что он обеспечивает правильное удаление выделенной памяти.

Базовый пример будет выглядеть так:

void fillArray(char* buffer, int sz) {
  char text[] = "hello there!";
  if (sizeof(text)>sz) {
    // overflow! Buffer is too small!
    return;
  }
  for (int n=0;n<sizeof(text);n++) {
    buffer[n] = text[n];
  }
}

int main() {
  char* buffer = new char[30]; // allocates a buffer of 30 bytes.
  fillArray(buffer,30);
  cout << buffer;
  delete [] buffer;
}

/* note that it would be easier to use static memory in this example */

Нетрудно подумать о проблеме.

2 голосов
/ 21 декабря 2012

Объявите массив как «статическую» переменную и вернитесь с его адресом.Этот код работает, но вызывает предупреждение:

#include <cstdlib>
#include <iostream>
using namespace std;

char* myBadFunction(){
    static char charArray[] = "Some string\n";    // insert "static"
    // char* charPointer = charArray;  
    return charArray;             // charArray is a pointer to the static array
}                                 // after returning static varibles stay safe
int main(int argc, char** argv) {
    cout << myBadFunction();
    return 0;
}
1 голос
/ 30 сентября 2016

«Некоторая строка \ n» является строковым литералом и поэтому будет существовать в течение всего времени жизни программы, поэтому допустимо следующее:

#include <cstdlib>
#include <iostream>

using namespace std;

char* myGoodFunction(){
    char* charPointer = "Some string\n";
    return charPointer;
}

int main(int argc, char** argv) {
    cout << myGoodFunction();

    return 0;
}

Конечно, это полезно, только если функциявозвращает ту же строку.Если возвращаемая строка может отличаться (обычно это так), то вы можете объявить массив char в вашей функции как статический и вернуть его адрес (как уже было предложено).

...