0

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

我猜这是因为当参数按值传递时,[copy-constructor] 被调用,如果它没有被程序员覆盖,默认的 [copy-constructor] 会执行 [shallow-copy] 而不是 [deep-copy] !

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

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

以下是导致修改列表的代码。此类的对象包含一个 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;
}
4

3 回答 3

2

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

于 2013-07-03T19:26:59.323 回答
1

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

是的,这是真的。

我猜这是因为当参数按值传递时,[copy-constructor] 被调用,如果它没有被程序员覆盖,默认的 [copy-constructor] 会执行 [shallow-copy] 而不是 [deep-copy] !

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

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

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

于 2013-07-07T05:43:12.380 回答
0

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

让我们考虑以下情况:

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

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

  1. 创造sizeof(int)空间b
  2. 复制b到空间
  3. 可以在不影响原件的情况下func修改本地副本bb

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

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

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

于 2013-07-03T20:13:59.877 回答