【问题标题】:VC++: Pass multiple arrays between functionsVC++:在函数之间传递多个数组
【发布时间】:2012-10-25 06:13:00
【问题描述】:

我是 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 arrays between functions 你没有 4 个数组。您有 1 个包含 4 个元素的数组。
  • 不,data0-4是实际在函数中动态分配的数组。
  • 我推荐阅读一些books on C++

标签: c++ arrays visual-c++ pointers


【解决方案1】:

为了补全前面的有效答案,我会尽量扩大答案:

我做对了吗?

好吧,为了在函数之间传递数据:是的,使用指针是一种选择。但社区通常不鼓励这种做法,因为它会给内存管理带来麻烦。

当您使用指向动态内存的指针时,您必须清楚地了解创建内存的位置和删除内存的位置,换句话说:内存的生命周期必须清晰明了,并且对于因此,通常不鼓励在函数之间传递指针。

例如,在您的情况下:unsigned int* step1(...) 函数返回一个指针,但看着它,新程序员或与您一起工作的人不会知道返回的指针是否是动态内存以及调用 step1 是否必须 @987654322 @ 或 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

【讨论】:

    【解决方案2】:

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

    并添加一些代码,这些函数将在其中使用。

    【讨论】:

    • std::vectors 是否也与 GCC 兼容?
    • 是的,STL 是 C++ 标准的一部分。
    • 但是当我这样做时,data 向量会在函数退出时被系统取消分配吗?
    • 是的。容器将控制对象的生命周期,并在容器被销毁时释放内存。无需手动调用删除算子。
    【解决方案3】:

    你需要一个指针数组,例如:

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

    【讨论】:

    • 你需要通过const引用传递vector以避免过度复制。
    【解决方案4】:

    假设您真的想要您所写的内容(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];
    

    几点说明:

    • 如果您想让这些“数组”可调整大小使用(或在一段时间后使用超过 4 个项目),请使用 std::vector 或另一个 STL Container
    • 如果这些数据夹有任何特殊含义(如 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 释放内存

    【讨论】:

    • 您的第一个示例无法在 VS2010 中编译。是说“C2440:'=':无法从'int *'转换为'int'”
    • 我需要动态分配数据数组,这样函数退出后它就不会被 GC。
    • 您的示例仍然无法在 VS2010 中编译,它显示“错误:现在允许类型名称”。错误位于new (*int)
    • @KevinBoyd 啊*int的反面,应该是(int*),这样试试
    【解决方案5】:

    我尝试了 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];
    
        ...
    
    }
    

    【讨论】:

      猜你喜欢
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 2019-06-28
      • 2019-04-28
      • 2016-12-15
      • 1970-01-01
      • 2014-03-20
      • 2021-11-20
      相关资源
      最近更新 更多