0

私は VC++ の初心者で、関数間で 4 つの配列を渡す必要があるため、別の配列を使用してポインターを格納しています。私はそれを正しくしましたか?

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];

    ...

}
4

5 に答える 5

3

以前の有効な回答を完了するために、回答を拡張しようとします。

私はそれを正しくしましたか?

さて、関数間でデータを渡すために: はい、ポインターを使用してそれを行うことはオプションです。しかし、メモリ管理が面倒になるため、コミュニティでは一般的に推奨されていません。

動的メモリを指すポインターを使用する場合、メモリが作成される場所とメモリが削除される場所の明確なイメージを持っている必要があります。つまり、メモリのライフサイクルは明確かつ単純でなければならず、この理由から、関数間でポインタを渡すことは一般的に推奨されません。

たとえば、あなたの場合:unsigned int* step1(...)関数はポインターを返しますが、それを見ると、新しいプログラマーまたはあなたと一緒に働く人は、返されたポインターが動的メモリであるかどうか、および step1 を呼び出す必要があるかどうか、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

于 2012-10-25T07:06:50.400 に答える
1

問題の内容 (4 つの配列を 1 つにグループ化) が本当に必要であると仮定すると、まず次のように 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];

いくつかのメモ:

  • これらの「配列」をサイズ変更可能にしたい場合(または、後で4つ以上のアイテムを使用したい場合)std::vectorまたは別のSTLコンテナを使用します
  • これらのデータ チャックに特別な意味がある場合 ( data1= ユーザー ID、data2= ビジター ID など)、それらに名前を付けるクラスまたは構造を構築します。

    // 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

于 2012-10-25T06:42:56.807 に答える
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];

そして、これらの関数が使用されるコードを追加します。

于 2012-10-25T06:17:59.547 に答える
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;
}
于 2012-10-25T06:19:24.673 に答える
0

Vyktor のソリューションを試しましたが、うまくいきませんでした。私は最終的に、普通の配列(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];

    ...

}
于 2012-10-25T08:45:43.430 に答える