[C++传递值]:被调用函数是否可以修改原始变量的内容

[C ++ pass-by-value]: can the content of the original variables get modified by the called function?

本文关键字:修改 原始 变量 是否 函数 C++ 调用      更新时间:2023-10-16

我一直认为,在[c++]中传递带有[pass-by-value]的变量会生成它们的副本,因此接收这些副本的函数不能更改原始变量的内容。

我想这是因为当参数通过值传递时,会调用[复制构造函数],如果程序员没有重写它,默认的[复制构造函数'会执行[浅复制]而不是[深度复制]!

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

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

下面是我的代码,它导致了一个修改的列表。此类的对象包含一个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。然后打印23!

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;
}

你是对的。浅复制(如果你的类缺少复制构造函数,就会发生这种情况)复制类中的指针,但不是它们指向的指针。如果你想正确地按值传递非常量对象,你必须定义一个执行深度复制的复制构造函数。

我一直认为在[c++],生成它们的副本,因此接收这些的函数副本不能更改原始变量的内容。

是的,这是真的。

我想这是因为当参数通过值传递时,调用了[copy constructor],如果它未被程序员,默认的[复制构造函数]会执行[浅复制]的[深度复制]!

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

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

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

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

让我们考虑以下情况:

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&,所以它的处理方式与int b相同。

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