[C ++ pass-by-value]: может ли содержимое исходных переменных быть модифицировано вызываемой функцией?

Я всегда предполагал, что передача переменных с [pass-by-value] в [c ++] делает их копию, и поэтому функция, получающая эти копии, не может изменять содержимое исходной переменной.

Я думаю, это потому, что когда аргумент передается по значению, вызывается [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;
}

0

Решение

Ты прав. Мелкая копия (которая возникает, если в вашем классе отсутствует конструктор копирования) копирует указатели в вашем классе, но не то, на что они указывают. Вы должны определить конструктор копирования, который выполняет глубокое копирование, если вы хотите правильно передавать неконстантный объект по значению.

1

Другие решения

Поэтому мой вопрос заключается в том, почему они назвали его передачей по значению, тогда как в случае наличия указателей в классе функция имеет доступ к ссылке на этот указатель и может повредить ее.

Давайте рассмотрим следующую ситуацию:

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

для первого параметра, b, это доставка «ByVal», так что компилятор обычно делает

  1. Создайте sizeof(int) пространство для b
  2. копия b в космос
  3. func можно изменить локальную копию b не влияя на оригинал b

Это необходимо, поскольку, если он автоматически доставляется «ByRef», компилятор столкнется с проблемой, когда будет задано не L-значение, т. Е. 1, поскольку вы не можете получить ссылку из константного значения.

Теперь давайте посмотрим, что происходит с c, Опять же, он имеет тип int*не int&таким образом, он рассматривается так же, как int b,

Однако когда c это int* указатель, он не хранит никаких других данных, кроме адрес к некоторому объекту с типом int. Таким образом, косвенный доступ через указатель разрешен, и существует только копия адрес но не значение, на которое оно указывает, поэтому может быть повреждено.

0

Я всегда предполагал, что передача переменных с [передачей по значению] в
[c ++], делает их копию, и поэтому функция, получающая эти
копии не могут изменить содержимое исходной переменной.

Да, это правда.

Я думаю, это потому, что когда аргумент передается по значению,
[copy-constructor] вызывается, и если он не переопределен
программист, по умолчанию [copy-constructor] делает [shallow-copy] вместо
[глубокая копия]!

Копия» является «мелкая копия». «Копия» копирует все содержимое объектов. И содержимое поля. И если поле является указателем, то содержимое является указателем, адресом. Вот и все.

Так что мой вопрос заключается в том, почему они назвали это по стоимости, а в
В случае наличия указателей в классе, функция имеет доступ к
ссылка на этот указатель и может повредить его.

Так? То, на что указывают эти указатели, не является частью объекта. Так что это не имеет значения. Указатель является частью объекта.

0
По вопросам рекламы [email protected]