2010-11-23 5 views
4

Я новичок в C++, и я хочу знать, как я могу вернуть массив из C++.
Я пробовал следующий код, но, похоже, не работает.Как вернуть массив в C++?

char some_function(){ 
    char my_string[] = "The quick brown fox jumps over the lazy dog"; 
    return my_string; 
} 
+0

Возвращаемый тип этой функции один символ - не массив символов. Тем не менее, указание типа возврата массива не поможет - см. Ответы о пшеницах. – Steve314 2010-11-23 06:05:22

ответ

5

Причина, по которой код не работает, заключается в том, что в тот момент, когда функция заканчивается, так же как и время жизни созданной строки. Вместо этого, если вы собираетесь работать на C++, используйте std::string и верните это.

std::string myFunc(){ 
    return string("hey a new string"); 
} 

Для других массивов используют std::vector, std::deque или один из других классов STL. Я бы также указать вам взглянуть на STL (стандартная библиотека шаблонов):

vector<float> myFunc(){ 
    vector<float> blah; 
    blah.push_back(4.5); 
    blah.push_back(5.7); 
    return blah; 
} 

На вернувшихся массивы:

Большая проблема с указателями и такие есть соображения жизни объекта. Такие, как следующий код:

int* myFunc(){ 
    int myInt = 4; 
    return &myInt; 
} 

, что происходит здесь является то, что при выходе из функции myInt больше не существует оставляя указатель, который был возвращен будет указывать на какой-то адрес памяти, который может или не может содержать значение 4. Если вы хотите, чтобы вернуть массив с помощью указателей (я действительно предлагаю вам не использовать и std::vector) это будет выглядеть примерно так:

int* myFunc(){ 
    return new int[4]; 
} 

, который использует новый оператор.

+0

Какой заголовок я должен включить? Могу ли я вернуть целочисленный массив без stl? – SteepCurver 2010-11-23 05:45:23

+0

@ScienceCrazy для `std :: string` это` #include `, а также писать` using std :: string` в верхней части файла. Также я отредактировал свой ответ. Я настоятельно рекомендую вам не использовать голые указатели при возврате из функции, поскольку вызывающий не знает, несут ли они ответственность за очистку указанной памяти. – wheaties 2010-11-23 05:51:10

+0

Вы должны придерживаться метода `std ::` везде или вообще не использовать его. – zneak 2010-11-23 05:58:44

2

В C++ лучше использовать std::string по массиву char практически в каждом случае.

В более общем плане рассмотрите STL container classes, а не массивы в стиле C.

Вот несколько примеров ...

#include <string> 
#include <vector> 

std::string some_function() 
{ 
    return "The quick brown fox jumps over the lazy dog"; 
} 

std::vector<std::string> some_other_function() 
{ 
    std::vector<std::string> stuff; 
    stuff.push_back("Spam"); 
    stuff.push_back("Spam"); 
    stuff.push_back("Spam"); 
    stuff.push_back("Spam"); 
    stuff.push_back("Spam"); 
    stuff.push_back("Spam"); 
    stuff.push_back("Spam"); 
    return stuff; 
} 
0

Это приведет к краху из-за модели памяти.

В C++ (как на многих других языках) есть два двух популярных места, где вы можете выделить память: стек и кучу.

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

Надеюсь, есть место, где данные могут жить вечно («навсегда» - это продолжительность вашей программы): куча. Если вы выделите что-то в куче, он не будет очищен, когда функция вернется. Однако это подразумевает дополнительную бухгалтерскую отчетность, поскольку вы можете легко потерять все ссылки на определенный блок выделенной памяти; и если вы это сделаете, нет способа вернуть его (это называется утечкой, и это очень плохо). Поэтому было предложено правило: если функция выделяет память в куче, она должна нести ответственность за ее освобождение. Проблема в том, что если ваша функция возвращает выделенную память, она не может ее избавиться. Поэтому вы не должны выделять память в куче и возвращать ее.

Итак, если вы не можете выделить свой массив в стеке, и вы не можете вернуть указатель на память в кучу, что вы можете сделать?

Предлагаю вам использовать типы C++ для решения вашей проблемы. Если вы собираетесь использовать массив символов, лучшим будет std::string (#include <string>). Если вы собираетесь использовать массив любого другого, лучшим может быть std::vector<YourTypeHere> (#include <vector>). Оба управляют своей собственной памятью, и поэтому их можно вернуть.

Существует достаточно документации для обоих здесь и в Google. В любом случае, это быстрый пример.

std::vector<int> foo() 
{ 
    std::vector<int> my_vector; 
    my_vector.push_back(1); 
    my_vector.push_back(2); 
    my_vector.push_back(3); 
    return my_vector; 
} 

std::string bar() 
{ 
    std::string my_string = "The quick brown fox jumps over the lazy dog"; 
    return my_string; 
} 

int main() 
{ 
    std::vector<int> my_vector = foo(); 
    // will print 123 
    std::cout << my_vector[0] << my_vector[1] << my_vector[2] << std::endl; 

    std::string my_string = bar(); 
    // will print The quick brown fox jumps over the lazy dog 
    std::cout << my_string << std::endl; 
} 
1

Если вы можете использовать стандартный контейнер, то вам следует. В вашем конкретном примере, контейнер, вы должны использовать это std::string, как:

#include <string> 
std::string some_function(){ 
    std::string my_string = "The quick brown fox jumps over the lazy dog"; 
    return my_string; 
} 

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

// notice here that we use 'string.h', with the '.h' extension, different from above 
#include <string.h> 


void some_function(size_t len, char * dest) 
{ 
    std::strncpy(dest, "The quick brown fox jumps over the lazy dog", len); 
} 

int main() 
{ 
    const std::size_t stringSize = 100; 
    char myString[stringSize]; 
    some_function(stringSize, myString); 
} 

Другой вариант, хотя и менее желательно во многих случаях - выделить новую область хранения для хранения массива.

char* some_function() 
{ 
    char* result = new char[44]; 
    strcpy(result, "The quick brown fox jumps over the lazy dog"); 
    return result; 
} 


int main() 
{ 
    char *myString = some_function(); 
    // do some stuff with myString 
    delete myString[]; 
} 
0

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

Один из альтернативных, если вы хотите что-то вернуть из функции вы передаете адрес, что функция и поместить переменные в этом адресе

void some_function(string& some_string){ 
    char my_string[] = "The quick brown fox jumps over the lazy dog"; 
    some_string = my_string; 
} 
0

Есть два способа сделать это без STL. Один использует параметр «out», а другой - злоупотребление структурой. Вот как первые работы:

#include <cstddef> // For ::std::size_t 
#include <cstring> // For strncpy 
void some_function(char retval[], ::std::size_t retval_len) { 
    char my_string[] = "The quick brown fox jumps over the lazy dog"; 
    ::std::strncpy(retval, my_string, retval_len); 
} 

Вот как второй будет работать:

struct array_struct { 
    char the_array[50]; 
}; 

array_struct some_function() { 
    array_struct ary = { "The quick brown fox jumps over the lazy dog" }; 
    return ary; 
} 
Смежные вопросы