【问题标题】:Resize Array Template调整数组模板大小
【发布时间】:2010-07-30 12:12:00
【问题描述】:

我需要一个模板函数来调整任何类型的数组。

这是我的尝试:

   class CCommon
    {
    template < typename T >
    static void ResizeArray(T* paArray, int iOldSize, int iNewSize, T tInitValue);
    }
    
    ..
    
   template < typename T >
   void CCommon::ResizeArray(T* paArray, int iOldSize, int iNewSize, T tInitValue)
    {
       T* paTmpArray = new T[iOldSize];
       for(int i = 0; i < iOldSize; i++)
       {
          paTmpArray[i] = paArray[i];
       }
       delete [] paArray;
       paArray=new T[iNewSize];
       for(int i=0; i < iNewSize; i++)
       {
          paArray[i] = tInitValue;
       }
       for(int i = 0; i < iOldSize; i++)
       {
          paArray[i] = paTmpArray[i];
       }
       delete [] paTmpArray;
    }

CCommon 文件甚至是可编译的,但如果我想使用它,我会得到错误:

Fehler 2 错误 LNK2019:Verweis auf nicht aufgelöstes externes 符号 (“未解决的外部引用”。)

""public: 静态无效 __cdecl CCommon::ResizeArray(int *,int,int,int)" (??$ResizeArray@H@CCommon@@SAXPAHHHH@Z)" 在 Funktion ""public: void __thiscall CWaebi_OBJ::ReInit(void)" (?ReInit@CWaebi_OBJ@@QAEXXZ)".CWaebi_OBJ.obj

Fehler 3 致命错误 LNK1120: 1 nicht aufgelöste 外部

我想这样称呼它:

#include CCommon

SomeFunction
{
..
CCommon::ResizeArray<BOOL>( mTextIndexMask, m_iNumberOfLastTextMaskArray, mTextCount, FALSE );
..
}

怎么了?

尊敬的大人

【问题讨论】:

  • 大多数 SO 用户将无法阅读错误消息。
  • “未解决的外部引用”。
  • 还有一个 .cpp 文件中的模板定义。
  • 您可能希望通过引用传递指针--与问题无关,而是一个错误--。此外,您的功能成本高昂(您复制的内容超出了您的需要),并且无论如何都不是异常安全的。
  • @Donotalo: "Verweis auf nicht..." 是德语; “??$ResizeArray@H@CCommon@@SAXPAHHHH@Z”是湿气蒸发器的二进制语言。

标签: c++


【解决方案1】:

首先,你到底为什么要使用一些自定义的BOOL 类型而不是C++ 的内置bool

其次,听起来您已将模板实现放在源文件中。 CCommon::ResizeArray 的实现是否包含在您调用它的 ccommon.h 文件中?如果没有,请将其放在那里(或包含在其中的文件中)。模板需要在头文件中完成整个实现才能工作。不能像普通函数和方法那样在头文件中声明和在源文件中定义定义。

【讨论】:

    【解决方案2】:
    template < typename T >
    void CCommon::ResizeArray(T* paArray, int iOldSize, int iNewSize, T tInitValue)
    {
     T* paTmpArray = new T[iOldSize];
     for(int i = 0; i < iOldSize; i++)
     {
      paTmpArray[i] = paArray[i];
     }
     delete [] paArray;
     paArray=new T[iNewSize];
     for(int i=0; i < iNewSize; i++)
     {
      paArray[i] = tInitValue;
     }
     for(int i = 0; i < iOldSize; i++)
     {
      paArray[i] = paTmpArray[i];
     }
     delete [] paTmpArray;
    }
    

    那是行不通的。调用该函数后 paArray 的值不会改变。你会得到内存泄漏,而且在调用之后 paArray 将指向垃圾。 此外,您不需要将其设为静态类函数。使用模板功能就足够了。 而且你不需要临时数组。

    使用这样的东西:

    #include <stdio.h>
    
    template <typename T> void resizeArray(T*& arr, int oldSize, int newSize, const T initVal){
        T* newArray = new T[newSize];
    
        for (int i = 0; (i < oldSize)&&(i<newSize); i++)
            newArray[i] = arr[i];
    
        for (int i = oldSize; i < newSize; i++)
            newArray[i] = initVal;
    
        delete[] arr;
        arr = newArray;
    }
    
    int main(int argc, char** argv){
        const int startSize = 26, newSize = 42;
        int* p = new int[startSize];
        for (int i = 0; i < startSize; i++)
            p[i] = i;
    
        resizeArray(p, startSize, newSize, 87);
    
        for (int i = 0; i < newSize; i++)
            printf("%d\n", p[i]);
        delete[] p;
        return 0;
    }
    

    或者这个:

    #include <stdio.h>
    #include <algorithm>
    
    template <typename T> void resizeArray(T*& arr, int oldSize, int newSize, const T initVal){
        T* newArray = new T[newSize];
    
        std::copy(arr, arr+std::min(oldSize, newSize), newArray);
    
        if (oldSize < newSize)
            std::fill(newArray+oldSize, newArray+newSize, initVal);
    
        delete[] arr;
        arr = newArray;
    }
    
    int main(int argc, char** argv){
        const int startSize = 26, newSize = 42;
        int* p = new int[startSize];
        for (int i = 0; i < startSize; i++)
            p[i] = i;
    
        resizeArray(p, startSize, newSize, 87);
    
        for (int i = 0; i < newSize; i++)
            printf("%d\n", p[i]);
        delete[] p;
        return 0;
    }
    

    改为。

    【讨论】:

    • 仍然不是异常安全的(对新数组使用auto_ptr,然后在所有副本成功后释放它)。嗯,显然不是auto_ptr,它不能处理数组,而是它的数组版本。
    【解决方案3】:

    我猜你正试图在 .cpp 文件中定义你的模板成员函数。 这是不好的。模板取决于在实例化时解析的类型,具有生成正确代码的完整定义。 解决方案:将您的定义放在 .hxx 文件中,包含在您的 .h 中。

    【讨论】:

      【解决方案4】:

      一旦您修复了 cpp 问题中的模板 (@Tyler McHenry),您的 ResizeArray 仍然无法工作,因为您永远不会将新分配的数组返回给调用者。 要么你必须返回它,要么接受一个 T** 作为参数。

      【讨论】:

        【解决方案5】:

        您似乎试图将实现放在 *.cpp 文件中。模板必须在标头中实现。

        另一点是您的代码中存在一个主要错误: 您根本不返回新指针,您只会覆盖参数的本地副本。 这意味着新分配的内存被泄露,之后任何试图访问该数组的代码都可能会崩溃。

        哦,还有一个提示:为什么要将数组内容复制到临时变量中?您可以分配一个新大小的数组,将内容复制到该数组中,删除旧数组并返回新指针或将 pArray 设为 T** 并将新数组指针分配给该数组。

        最后一点,我建议使用std::copystd::fill 操作来复制/填充数组内容,例如: 而不是

        for(int i = 0; i < iOldSize; i++)
        {
            paTmpArray[i] = paArray[i];
        }
        

        使用

        std::copy(paArray, paArray+iOldSize, paTmpArray);
        

        它导致代码越来越简洁,并且可能比循环执行更优化。

        所以我建议这样做:

        #include <algorithm>
        template < typename T >
        void CCommon::ResizeArray(T*& paArray, int iOldSize, int iNewSize, T tInitValue)
        {
         T* paTmpArray = new T[iNewSize];
         std::copy(paArray, paArray + std::min(iNewSize, iOldSize), paTmpArray);
         delete[] paArray;
         if(iNewSize > iOldSize)
             std::fill(paTmpArray + iOldSize, paTmpArray + iNewSize, tInitValue);
         paArray = paTmpArray;
        }
        

        【讨论】:

        • 这样吗? BOOL* tmpTextIndexMask = new BOOL[iNewSize]; for(int i=0; i
        • "std::copy(paTmpArray, paTmpArray+iOldSize, paArray);"如果新尺寸小于旧尺寸,则会崩溃。
        • 如果您的 mTextIndexMask 是 BOOL**(并且您使用 *mTextIndexMask =..)或 BOOL*& 那么是的。否则你仍然有你没有返回你的值的错误。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-10
        • 1970-01-01
        相关资源
        最近更新 更多