【问题标题】:[C ++ pass-by-value]: can the content of the original variables get modified by the called function?[C++ pass-by-value]:被调用函数可以修改原始变量的内容吗?
【发布时间】:2013-07-01 15:27:56
【问题描述】:

我一直假设在 [c++] 中使用 [pass-by-value] 传递变量会复制它们,因此接收这些副本的函数不能更改原始变量的内容。

我猜是因为当参数按值传递时,[copy-constructor]被调用,如果没有被程序员重写,默认的[copy-constructor]是[shallow-copy]而不是[deep -复制]!

所以我的问题是为什么他们称它为按值传递,而在类中有指针的情况下,函数可以访问该指针的引用并可能损坏它。还有这个结论正确吗? “只要在类中有指针,并且您可以按值传递该类的对象作为函数参数,请定义复制构造函数!”

如果这个错误很有名,有人知道这个问题的名称或短语吗?

以下是导致修改列表的代码。此类的对象包含一个 int 成员变量 以及指向节点成员变量列表的指针。

class ComplicatedObject{  
  public:
    ComplicatedObject();
    ~ComplicatedObject();

    //ComplicatedObject(const ComplicatedObject& c);  // copy construtor
    //ComplicatedObject& operator=(const ComplicatedObject& c); // =operator

    int int_member_varialbe_;  // an int member variable
    void addToList(int d);
    void printList();

  private:
    struct node{
      int data;
      node* next;
    };
    node* head_;  // points to the beginning of a list (linkedlist of int)
};

下面的代码打印 2。然后打印 2 3 !

Test.cpp:

void myfunction(ComplicatedObject obj){
  obj.addToList(3);
  obj.int_member_variable_ = 5;
}

int main(void){
  ComplicatedObject c_object;
  c_object.addToList(2);
  c_object.printList();  //prints 2 

  cout << "int member variable befor passing:";
  cout << c-object.int_member_variable_ << endl;  //prints 6 (a default value)

  myfunction(c_object); //pass-by-value

  cout << "int member variable after passing:";
  cout << c-object.int_member_variable_ << endl;  // prints 6 (not 5)

  c_object.printList(); // prints 2 3 ! List get changed!

  return 0;
}

【问题讨论】:

  • 如果你的类有你浅拷贝的指针,它可以。
  • 列表发生变化,因为您正在对对象进行浅拷贝。
  • 问题的名称是“Pointers Are Evil”(M. Cline)
  • 指针有一个值,默认情况下该值被复制。这个值是另一个值的地址。您可以编写一个value_ptr&lt;T&gt; 智能指针类,默认情况下它会逐个复制(无论是克隆、复制构造还是您拥有的)。至于为什么默认会发生这种情况?好吧,structclass 上的默认 operator= 行为是在 C++ 从 C 拆分之前确定的。
  • 想象一下最糟糕的情况,如果您删除第一个指针然后尝试访问第二个指针会发生什么!顺便说一句,黄金法则是几乎从不使用原始指针。

标签: c++ copy-constructor argument-passing pass-by-value shallow-copy


【解决方案1】:

你是对的。浅拷贝(如果您的类缺少复制构造函数,则会发生这种情况)复制类中的指针,而不是它们指向的指针。如果您希望能够按值正确传递非常量对象,则必须定义一个复制构造函数来执行深层复制。

【讨论】:

    【解决方案2】:

    我一直假设使用 [pass-by-value] 传递变量 [c++],复制它们,所以函数接收这些 副本不能改变原始变量的内容。

    是的,没错。

    我猜是因为当参数按值传递时, [copy-constructor] 被调用,如果它没有被 程序员,默认的 [copy-constructor] 改为 [shallow-copy] [深拷贝]!

    “复制”“浅复制”。 “副本”复制对象的所有内容。内容是字段。如果字段是指针,那么内容就是指针,地址。就是这样。

    所以我的问题是,为什么他们称它为按值传递,而在 在类中有指针的情况下,函数可以访问 该指针的引用并可能损坏它。

    所以?这些指针指向的东西不是对象的一部分。所以这无关紧要。指针是对象的一部分。

    【讨论】:

      【解决方案3】:

      所以我的问题是为什么他们称它为按值传递,而在类中有指针的情况下,函数可以访问该指针的引用并可能损坏它。

      让我们考虑以下情况:

      int func(int b, int* c)
      {
        /* some stuff */
      }
      

      对于第一个参数b,它是一个“ByVal”传递,所以编译器通常做的是

      1. b 创建sizeof(int) 空间
      2. 复制b到空间
      3. func可以修改b的本地副本而不影响原来的b

      这是必要的,因为如果自动传递“ByRef”,当给定非L值时,编译器会遇到麻烦,即1,因为你无法从常量值中获取引用。

      现在让我们看看c 会发生什么。同样,它的类型为int*,而不是int&amp;,因此它的处理方式与int b 相同。

      但是,当cint* 指针时,它不会将除地址 之外的任何其他数据存储到某个类型为int 的对象中。因此允许通过指针进行间接访问,并且只有地址的副本,而不是它指向的值,因此可能会被损坏。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-04
        • 1970-01-01
        • 2020-01-22
        • 2012-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多