[C ++ pass-by-value]:原始变量的内容可以被被调用函数修改吗?

时间:2013-07-03 19:23:55

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

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

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

所以我的问题是他们为什么称它为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.然后打印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;
}

3 个答案:

答案 0 :(得分:1)

你是对的。浅层副本(如果您的类缺少复制构造函数,则会出现)复制类中的指针,但不会复制它们指向的指针。如果您希望能够按值正确传递非const对象,则必须定义一个执行深层复制的复制构造函数。

答案 1 :(得分:0)

  

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

让我们考虑以下情况:

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

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

  1. sizeof(int)
  2. 创建b空间
  3. b复制到空间
  4. func可以修改b的本地副本,而不会影响原始b
  5. 这是必要的,因为如果它自动传递“ByRef”,编译器将在给出非L值时遇到麻烦,即1,因为你无法从常数值获得引用。

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

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

答案 2 :(得分:0)

  

我一直假设用[pass-by-value]传递变量   [c ++],制作它们的副本,以及接收这些的功能   副本无法更改原始变量的内容。

是的,那是真的。

  

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

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

  

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

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