【问题标题】:C++ shallow/deep copy?C++ 浅/深拷贝?
【发布时间】:2011-09-23 19:09:20
【问题描述】:

我有这个功能

int getrelation(string name, RELATION& output){

        bool found=0;
        int index=0;
        for(int i=0;i<a_attributes.size();i++){
            if(name==a_attributes[i].str_name){
                found=1;
                index=i;
            }
        }
        if(!found){
            printf("relation not found");
            return 1;
        }
        output=a_attributes[index];  

        return 0;
    }

RELATION 是一个类 a_attributes 是关系向量。

它应该返回对关系对象的引用。在调用getrelation() 之后,如果我改变了输出的值,那么a_attributes[index] 的值也应该改变,因为这是一个浅拷贝,对吧?

【问题讨论】:

  • 我认为您在到达提问位置之前按下了“发布答案”按钮。阅读faq,了解什么是好问题。
  • 这里没有问题。问题以问号 (?) 结尾。
  • 这里唯一的 C++ 是参考。

标签: c++ reference pass-by-reference deep-copy


【解决方案1】:

这真的取决于你的赋值运算符,这里没有列出。

线

output=a_attributes[index];

将使用赋值运算符来设置输出。如果该赋值运算符进行深拷贝,那么您将得到深拷贝。

【讨论】:

    【解决方案2】:

    如果你没有重载赋值运算符,那么不,你不会得到浅拷贝。当您分配output=a_attributes[index]; 时,您正在制作a_attributes[index] 的副本。因此,对返回值的任何修改都不会影响a_attributes

    如果你想要一个浅拷贝,那么你必须要么overload the assignment operator,要么通过引用传递一个指针,通过将参数更改为RELATION&amp; *output,并传入一个指针,然后将最后一行更改为@987654327 @。

    您的代码还有另一个问题。您不能像在if(name==a_attributes[i].str_name) 行中那样直接将字符串与== 进行比较,因为只有当字符串存储在同一位置时它才会返回true。你需要使用strcmp()之类的东西。

    【讨论】:

      【解决方案3】:

      不,因为你这里是深拷贝。 output 参数是对 RELATION 类的某个对象的引用。因此,如果您在 getrelation 函数中更改该对象,那么用户会注意到这些更改,因为您更改了引用的对象。但是,在这一行 - output=a_attributes[index]; 上,您实际上调用了对象 output 的复制赋值运算符,它对从 a_attributes[index] 返回的对象到 output 引用的对象的每个字段进行深层复制,除非复制赋值运算符重载并执行不同的操作。这基本上是因为您不能更改引用的值 - 例如,它不能引用一个对象并最终引用另一个对象。为了实现你想要的(如果我理解正确的话),你必须传递一个指向对象指针的指针(或对指针的引用),然后你可以通过取消引用来更改指向对象的指针。像这样的:

      int getrelation(string name, RELATION **output){
              bool found=0;
              int index=0;
              for(int i=0;i<a_attributes.size();i++){
                  if(name==a_attributes[i].str_name){
                      found=1;
                      index=i;
                  }
              }
              if(!found){
                  printf("relation not found");
                  return 1;
              }
              *output= &a_attributes[index];
              return 0;
          }
      

      希望对你有帮助!

      【讨论】:

        【解决方案4】:

        不...如果您想获得对输出对象的引用,则将RELATION 类型的指针引用传递给函数,而不是@ 类型的对象引用987654322@.

        例如:

        int getrelation(string name, RELATION*& output)
        {
            bool found=0;
            int index=0;
            for(int i=0;i<a_attributes.size();i++){
                if(name==a_attributes[i].str_name){
                    found=1;
                    index=i;
                }
            }
            if(!found){
                printf("relation not found");
                return 1;
            }
            output = &(a_attributes[index]);  //take the address-of object
        
            return 0;
        }
        

        然后你会像这样调用你的函数:

        RELATION* ptr_to_object = NULL;
        string argument_name;
        //...more code to initialize argument_name
        
        if (getrelation(argument_name, ptr_to_object) == 1)
        {
            //...handle error condition
        }
        
        //now ptr_to_object points to your a_attribute[index] object
        

        所以此时,您现在可以取消引用ptr_to_object,您将获得a_attribute[index] 处的对象。然后,您可以通过取消引用指针来更改该对象的属性。唯一的警告是您不应该在ptr_to_object 上调用delete,因为它不“拥有”被指向的对象,并且返回的指针不指向使用@987654329 分配的内存段的开头@。此外,如果容器a_attribute 处理了对象(即,如果它是std::mapstd::vector),那么指针将指向无效的内存位置。因此,您必须确保容器的寿命超过您用作对象引用的指针。

        【讨论】:

          【解决方案5】:

          这里有一些更惯用的 C++,尽管返回实际的迭代器也是一个好主意。

          struct rel_by_name : public std::binary_function<const std::string&, const RELATION&, bool> {
            bool operator()(const std::string& s, const RELATION& rel) {
              return s == rel.str_name;
            }
          };
          
          RELATION& getrelation(const std::string& name) {
            std::vector<RELATION>::iterator it = std::find_if(a_attributes.begin(), a_attributes.end(),
                                                              std::bind1st(rel_by_name(), name));
            if(it == a_attributes.end()) {
              //not found, report error by throwing or something
            }
            else { return *it; }
          }
          

          您可能想要添加一个返回 const Relation&amp; 的 const 重载。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-04-12
            • 2015-01-13
            • 2011-09-05
            • 1970-01-01
            • 1970-01-01
            • 2012-07-06
            • 1970-01-01
            相关资源
            最近更新 更多