2012-10-25 3 views
0

Я довольно новичок в VC++, и мне нужно передать 4 массива между функциями, поэтому я использую другой массив для хранения указателей. Правильно ли я сделал это?VC++: передать несколько массивов между функциями

unsigned int* step1(...) { 

    ... 

    // save data arrays 
    unsigned int* savedData = new unsigned int[4]; 
    savedData[0] = *data0; 
    savedData[1] = *data1; 
    savedData[2] = *data2; 
    savedData[3] = *data3; 
    return savedData; 
} 

unsigned char* step2(unsigned int* savedData, ...) { 

    // read data arrays 
    unsigned int* data0 = &savedData[0]; 
    unsigned int* data1 = &savedData[1]; 
    unsigned int* data2 = &savedData[2]; 
    unsigned int* data3 = &savedData[3]; 

    ... 

} 
+0

'4 массива между функциями' У вас нет 4 массивов. У вас есть 1 массив, содержащий 4 элемента. –

+0

Нет, data0-4 - это фактические массивы, динамически распределенные в функции. –

+0

Я рекомендую прочитать некоторые [книги на C++] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). –

ответ

1

Использование std :: vector.

std::vector<int> data; 
data.push_back(data0); 
data.push_back(data1); 
data.push_back(data2); 
data.push_back(data3); 

И

int data0 = data[0]; 
int data1 = data[1]; 
int data2 = data[2]; 
int data3 = data[3]; 

И добавить некоторый код, в котором будет использоваться эти функции.

+0

являются 'std :: vector' совместимыми с GCC также? –

+0

Да, STL является частью стандартного C++. – kuperspb

+0

Но когда я это сделаю, будет ли вектор 'data' получить unallocated системой, когда функция выйдет? –

1

Вам понадобится массив указателей, например:

//The function that takes the array 
void foo(char ** data) 
{ 
    std::cout << data[0]; 
    std::cout << data[1]; 
    std::cout << data[2]; 
} 

main() 
{ 
    char * str = "aaa"; 
    char * str1 = "sss"; 
    char * str2 = "ddd"; 
    char ** res = new char *[3];//here's your array that has 3 elements each of which is a pointer. 
    res[0]=str; 
    res[1]=str1; 
    res[2]=str2; 
    foo(res); 
    return 0; 
} 

Выход будет

aaasssddd 

Немного лучший способ:

Было бы лучше использовать stl вместо обычных указателей, поскольку они проще и безопаснее использовать. С указателями, он будет работать точно так же:

void foo(std::vector< char * >vec) 
{ 
    std::cout << vec[0]; 
    std::cout << vec[1]; 
    std::cout << vec[2]; 
} 

main() 
{ 
    char * str = "aaa"; 
    char * str1 = "sss"; 
    char * str2 = "ddd"; 
    std::vector< char * >vec; 
    vec.push_back(str); 
    vec.push_back(str1); 
    vec.push_back(str2); 

    foo(vec); 
return 0; 
} 

Еще улучшенный способ:

И, наконец, лучший способ заключается в использовании строки:

void foo(std::vector<std::string>vec) 
{ 
    std::cout << vec[0]; 
    std::cout << vec[1]; 
    std::cout << vec[2]; 
} 

main() 
{ 
    std::string str = "aaa"; 
    std::string str1 = "sss"; 
    std::string str2 = "ddd"; 
    std::vector<std::string>vec; 
    vec.push_back(str); 
    vec.push_back(str1); 
    vec.push_back(str2); 

    foo(vec); 
return 0; 
} 
+1

Вам необходимо передать вектор по ссылке const, чтобы избежать чрезмерного копирования. – kuperspb

1

Предполагая, что вы действительно хотите что вы написали (4 массива, сгруппированные в один), в первую очередь вам нужны 4 массива, например int:

int data1[] = {1,2,3,4}; 
int data2[] = {5,6,7,8,9,10}; 
int *data3; // Let's say those two were allocated by malloc/new 
int *data4; 

// Now array that will contain those values 
int **data = new (int*)[4]; // int * = your datatype (array of ints) 
          // (int*)[] = array of arrays of ints 
data[0] = data1; 
data[1] = data2; 
data[2] = data3; 
data[3] = data4; 


// And reverse function 
data1 = data[0]; 
data2 = data[1]; 
data3 = data[2]; 
data4 = data[3]; 

Несколько замечаний:

  • , если вы хотите, чтобы эти «массивы» Resizeable использовать (или использовать более 4 пунктов после того, как время) использовать std::vector или другой STL Container
  • если эти Патроны данные имеют какие-либо специальные смысл (как data1 = пользовательские идентификаторы, data2 = идентификаторы посетитель, ...) построить класс или структуру, которая будет называть их:

    // In C: 
    struct user_data{ 
        int *user_ids; 
        int *visitor_ids; 
        char **unregistered_user_names; // Feel free to use another types 
    } 
    
    // In C++ 
    class UserData { 
        std::vector<int> userIds; 
        std::vector<int> visitorIds; 
        std::vector<std::string> unregisteredUserNames; 
    } 
    
  • После того, как аль расположенные данные с new unsigned int [4] не забудьте освободить память с delete [] array

+0

Ваш первый пример не компилируется в VS2010.Является ли "C2440: '=': не может преобразовать из 'int *' в 'int' ' –

+0

И мне нужен массив данных, который будет динамически распределяться, чтобы он не получал GC'd после выхода функции. –

+0

Ваш пример до сих пор не компилируется в VS2010, он говорит: «Ошибка: имя типа теперь разрешено». Ошибка находится в строке 'new (* int)' –

3

Для того, чтобы завершить предыдущие действительные ответы, я буду стараться расширить ответ:

Have I done it correctly?

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

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

Например, в вашем случае: функция unsigned int* step1(...) возвращает указатель, но, глядя на него, новый программист или кто-то работает с вами, не сказал бы, если указатель Возвращается динамической памяти и, если вы звоните шаг1 должны delete или delete [] память после вызова, то же самое касается unsigned char* step2(unsigned int* savedData, ...) и будет более запутанной и хлопотной, потому что кто-то спросил бы: step2 изменит savedData?

Для того, чтобы исправить step2 проблему, вы можете изменить функцию:

unsigned char* step2(const unsigned int* const savedData, ...) 

путем добавления const вы говорите: «Эй step2 не собирается изменять содержимое savedData ни! изменяя адрес, на который он указывает ".

Но все предыдущие тексты бесполезны, так как не устраняют самую важную проблему: где освобождается память?

В step1 вы создаете память динамически, в памяти step2 эта память считывается, но ... delete скрыт где-то в коде, который вы не вставляете? или есть step3, ожидающий заботы о памяти?

Чтобы избежать все эти головные боли памяти, обычно рекомендуется использование STL контейнеров, как std::vector, контейнер будет заботиться управления памятью для вас, в вашем случае:

typedef std::vector<int> intvector; 
typedef std::vector<intvector> intintvector; 

void step1(intintvector &Data, ...) { 
    ... 
    // create data arrays 
    intvector data0, data1, data2, data3; 
    // fill data0, data1, data2, data3 
    // ... 
    // save data arrays. 
    Data.push_back(data0); 
    Data.push_back(data1); 
    Data.push_back(data2); 
    Data.push_back(data3); 
} 

void step2(const intintvector &savedData, ...) { 

    // read data arrays 
    intvector data0 = savedData[0]; 
    intvector data1 = savedData[1]; 
    intvector data2 = savedData[2]; 
    intvector data3 = savedData[3]; 
    // ... 
} 

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

Надеюсь, это поможет! : D

0

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

Обратите внимание, что этот подход считается «устаревшим», поскольку вам необходимо нераспределять массивы вручную, используя синтаксис delete [] myArray.

unsigned int** step1(...) { 

    ... 

    // save data arrays 
    unsigned int** savedData = new unsigned int*[4]; // ** means pointer to a pointer 
    savedData[0] = data0; // transfer the pointer value straight 
    savedData[1] = data1; 
    savedData[2] = data2; 
    savedData[3] = data3; 
    return savedData; 
} 

unsigned char* step2(unsigned int** savedData, ...) { /// input is pointer to pointer 

    // read data arrays 
    unsigned int* data0 = savedData[0]; // read pointer straight 
    unsigned int* data1 = savedData[1]; 
    unsigned int* data2 = savedData[2]; 
    unsigned int* data3 = savedData[3]; 

    ... 

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