簡體   English   中英

從函數返回動態分配的wchar_t *數組

[英]Returning array of dynamically allocated wchar_t* from a function

我有一個函數,其簽名如下:

GetCustomers( wchar_t** Name,int *count);

在main方法中:對客戶的調用如下所示:

GetCustomers( Name,&count);

功能的主體如下:(由於客戶數量未知,我試圖動態分配meomry)

GetCustomers( wchar_t** Name,int *count)
{
    //Logic to get customer count : Stored in int  myCustomersCount
    Names = new wchar_t*[myCustomersCount];

    for (int i=0; i < myCustomersCount; i++ )     
    {
        Names[i] = new wchar_t;
    }

    //Logic to get customer names in  wchar_t* strName = "Name1";
    Names[0] = strName;
    *count = myCustomersCount;
}

我認為這個實現將允許數組名稱正確地傳遞回Main()函數,並在堆上進行內存分配,但似乎無法正常工作。 這有什么不對? myCustomersCount似乎在調用者中是正確的。

PS:代碼編譯並執行但在Main接收的數組是垃圾。

你似乎在想C,而不是C ++。 我會用以下的東西:

std::vector<std::string> GetCustomers();

或(可能是首選的):

template <class outIt>
void GetCustomers(outIt output_iterator);

后者你會使用類似的東西:

std::vector<std::wstring> customers;

GetCustomers(std::back_inserter(customers));

第三個顯而易見的可能性是為您的customers類配備一個begin()end()成員函數,這些函數將迭代器返回給客戶數據。

Edit2:這是一些經過測試的演示代碼:

#include <stdio.h>
#include <string.h>
#include <wchar.h>

void GetCustomers(wchar_t ***names, int *count) { 
    static wchar_t *myCustomers[] = { 
        L"You",
        L"Him",
        L"Her"
    };
    int myCustomersCount = 3;
    wchar_t **temp = new wchar_t *[myCustomersCount];

    *count = myCustomersCount;
    for (int i=0; i<myCustomersCount; i++) {
        temp[i] = new wchar_t[wcslen(myCustomers[i])+1];
        wcscpy(temp[i], myCustomers[i]);
    }
    *names = temp;
}

int main() { 
    wchar_t **customers;
    int count;

    GetCustomers(&customers, &count);

    for (int i=0; i<count; i++)
        printf("%S\n", customers[i]);
    return 0;
}

我真的不確定你在這里要做什么; 從我對你的代碼的理解; 你試圖將一些字符串存儲到一個字符指針數組的數組中。

GetCustomers(wchar_t **Name, int *count) {
   Name = new wchar_t*[myCustomersCount];
   for(int i = 0; i < myCustomersCount; i++) {
     /* Get your customer name and store into strName */
     Name[i] = strName;
   }
   *count = myCustomersCount;
}

在主要的,大概你有這樣的東西

wchar_t *Name = NULL;

然后你說

GetCustomers( Name,&count);

這會按值傳遞Name,但您希望通過引用傳遞它:

GetCustomers( &Name,&count);

並且可能只是一個拼寫錯誤,但您的參數名稱是Name(單數),但您在函數中將其稱為Names(復數):

GetCustomers( wchar_t** Name,int *count)
{
    //Logic to get customer count : Stored in int  myCustomersCount
    Names = new wchar_t*[myCustomersCount];

在任何情況下,您都希望指定Name指向的位置,而不是指向自身:

*Names = new wchar_t*[myCustomersCount];

然后,為Names中的每個元素分配一個字符,然后用strName覆蓋第一個字符。 分配是不必要的(實際上是內存泄漏),你應該從strName分配給循環中的每個元素,正如Suroot的答案所做的那樣。

您的代碼有2個明確的問題和1個潛在的問題。 首先導致問題的主要問題: Name本身是按值傳遞的。 這意味着當你在new功能的第一行中分配給它時,你要分配給副本而不是原始副本! 您有三個選項:1)保持雙指針,讓調用者負責分配內存,並為數組可以容納的名稱數量添加第三個參數(推薦)或2)使Name成為三重指針( wchar_t*** Name )然后您可以通過解除引用來分配它: *Name = new wchar_t*[myCustomersCount]; 或者3)只返回wchar_t**因為你沒有使用傳遞的值來做任何事情。

然后是另一個明確的問題:當你為每個名稱分配內存時,你需要在那里使用new[]運算符,否則你只需要為一個wchar_t分配空間。

最后,潛在的問題。 您沒有顯示此代碼獲取每個客戶名稱的准確程度。 但是,如果strName指向每個客戶名稱重用的內存,並將它們全部放入數組中,那么您將不得不將每個名稱wstrcpy放入數組中。 如果沒有,那么您不需要為每個Names[i]分配內存,因為您可以將結果直接存儲到Names[i]

最后一點:只是從查看這段代碼看起來你的內存管理會遇到很多問題,因為看起來不清楚誰負責分配和釋放內存,這可能會導致內存泄漏。 盡量保持在同一位置分配和釋放內存的責任,你將減少許多潛在的麻煩 - 讓調用者在調用函數之前分配內存並讓調用者在完成內存時釋放內存用它。

/* changed */
wchar_t** GetCustomers( int *count)
{
    //Logic to get customer count : Stored in int  myCustomersCount
    wchar_t **Names = new wchar_t*[myCustomersCount];

    for (int i=0; i < myCustomersCount; i++ )     
    {
                              /* changed */
        Names[i] = new wchar_t[MAX_NAME_SIZE];
    }

    //Logic to get customer names in  wchar_t* strName = "Name1";
    Names[0] = strName; /* possible wstrcpy needed here? */
    *count = myCustomersCount;

    /* changed */
    return Names;
}

編輯如果你真的 絕對無法改變功能簽名,我能想到的唯一解決方案是展平你的數組並使用C內存函數(你也可以使用一系列new s和delete s,但為什么不使用realloc是什么時候才能實現的,而且你在不使用像STL這樣的其他C ++功能的情況下管理內存?):

GetCustomers( wchar_t **Names, int *count)
{
    //Logic to get customer count : Stored in int  myCustomersCount
    size_t names_size = 0;

    for (int i=0; i < myCustomersCount; i++ )     
    {
        strName = ???; // whatever you use to get the next name

        size_t old_names_size = names_size;
        names_size += (wstrlen(strName) + 1) * sizeof(wchar_t); //+1 for NULL
        *Names = realloc(*Names, names_size);

        if (!*Names) {
            // Memory allocation failed, log it, abort, do whatever
        }

        wstrcpy(Names[old_names_size], strName);
    }
    *count = myCustomersCount;
}

請注意,這假定Name已經初始化並指向可以存儲wchar_t*內存,就像原始版本假定count已經初始化並指向可以存儲int內存。

我想我會在一個新的答案中重新開始。

這是一個簡單的程序,可以完成我認為你正在嘗試做的事情,其約束條件是不得更改GetCustomers的簽名。

void GetCustomers(wchar_t** Names,int *count)
{
    // Allocate the array of names
    wchar_t **ar = new wchar_t*[3];
    // Allocate space for each name in the array
    ar[0] = new wchar_t[10];
    ar[1] = new wchar_t[10];
    ar[2] = new wchar_t[10];
    // Fill in the names
    wcscpy(ar[0],L"joe");
    wcscpy(ar[1],L"jim");
    wcscpy(ar[2],L"bob");
    // Return the array through the bad GetCustomers signature
    *Names = (wchar_t*)ar;
    *count = 3;
}

int wmain(int argc, wchar_t* argv[])
{
    // names is an array of strings
    wchar_t **names = NULL;
    int count;
    // Squeeze names into the dodgy GetCustomers signature
    GetCustomers((wchar_t**)&names,&count);

    // Delete each name
    for(size_t x = 0; x < count; ++x)
        delete[] names[x];
    // Delete the array
    delete[] names;

    return 0;
}

請注意,我已將函數內的強制轉換與main中的另一個匹配。 這樣我們就可以保留一切,除了那個討厭的GetCustomers簽名。

這有幫助嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM