C++需要一个浅拷贝,但并不完全如此

C++ expected a shallow copy but not exactly

本文关键字:不完全 浅拷贝 一个 C++      更新时间:2023-10-16

下面是Vector的一个模板类,用于存储不同类型的数据元素。在main中检查复制构造函数和的代码。我所期望的是,语句"cout<<vCHAR2[2]<<endl;"应该打印值"expense",因为复制承包商正在进行浅层复制,但打印"责任"。

有人能帮我吗?谢谢

template<typename T>
class Vector{
  private:
      T* ptr;
      int size;
  public:
      Vector<T>(int s = 10){
           size = s;
           if(size!=0)
           {
               ptr = new T[size];
           }else{
               ptr = 0;
           }
      }
      Vector<T>(const Vector<T> &copy){
            this->size=copy.getSize();
            if(size !=0)
            {
                 ptr=new T[size];
                 for(int i=0;i<size;i++)
                    ptr[i] = copy.ptr[i];    
            }else{
               this->ptr=0;
            }
      }
      ~Vector<T>(){
         if(size>0)
         {
            delete[] ptr;
         }
      }
      int getSize() const
      {
          return size;    
      }
      const Vector<T> & operator = (const Vector<T> &rhs){
            if(this!=&rhs)
                 delete [] this->ptr;
                 size = rhs.size;
                 if(size!=0)
                 {
                      ptr=new T[size];
                      for(int i=0;i<size;i++)
                              ptr[i] = rhs.ptr[i];
            }
            return *this;
      }
      T& operator[](int index){
         if(index>=0 && index<=size)
            return ptr[index];
      }
};    


int main(int argc, char *argv[])
{
  Vector<char*> vCHAR(10);
  vCHAR[0]="asset";
  vCHAR[1]="income";
  vCHAR[2]="liability";
  Vector<char*> vCHAR2(vCHAR);
  vCHAR[2] = "expense";
  cout << vCHAR[2] << endl;
  cout << vCHAR2[2] << endl;
  system("PAUSE");
  return EXIT_SUCCESS;
}

复制ctor执行深度复制,因此vCHAR2有自己的元素数组。因此,当您更改源Vector的元素时,它不需要查看。(当您通过strcpy()或访问vCHAR[2][0]='X';更改指向的数据时,它会看到它(前提是这不会使您的程序崩溃-因为您在字符串文字上操作)

vCHAR[2]="expense"时,您正在更改向量vCHAR内的指针,但vCHAR2[2]仍然指向旧位置。简而言之,没有指针的浅拷贝。如果在复制矢量时重新使用了源中的T*,那么您就会得到所需的内容。

您选择的实现向量的设计是危险的。若您决定使用一种节点分配方法来管理元素(而std::vector使用块分配方法),则必须小心指针和内存管理例程。您遇到的问题与如何使用指针有关:在T* ptr;T& operator[]中,包括数组复制例程。在您的示例中,您使用的是指向char-char**的指针(用char*替换模板)。如果您决定使用节点分配方法来设计自己的向量实现,我建议您也实现struct VectorTraits,并至少使用它来设计向量类。此外,我建议使用std::string而不是char*。

在行中:

Vector<char*> vCHAR2(vCHAR);

vCHAR2[2]是指向字符串"负债"的指针。线路

vCHAR[2] = "expense";

不会更改vCHAR2[2]的值,因为即使vCHAR[2]已更改,vCHAR2[3]仍指向"责任"。

要改变它,你只需要直接分配给它,即

vCHAR2[2] = "expense";

我认为你试图实现的是:

int* p = new int();
*p = 111;
int* q = p;
*p = 222; // change the content of what is pointed to
cout << *p << endl; // 222
cout << *q << endl; // 222 also

然而,这是一个不同的情况,因为我们正在改变所指向的内容。如果我们只做指针赋值,内容是不变的。只有指针被分配给另一个内存区域。

*p = 111;
int* q = p;
int z = 333;
p = &z; // do not change the content of what is pointed to, point to another area
cout << *p << endl; // 333
cout << *q << endl; // 222 still