Я всегда предполагал, что передача переменных с [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;
}
Ты прав. Мелкая копия (которая возникает, если в вашем классе отсутствует конструктор копирования) копирует указатели в вашем классе, но не то, на что они указывают. Вы должны определить конструктор копирования, который выполняет глубокое копирование, если вы хотите правильно передавать неконстантный объект по значению.
Поэтому мой вопрос заключается в том, почему они назвали его передачей по значению, тогда как в случае наличия указателей в классе функция имеет доступ к ссылке на этот указатель и может повредить ее.
Давайте рассмотрим следующую ситуацию:
int func(int b, int* c)
{
/* some stuff */
}
для первого параметра, b
, это доставка «ByVal», так что компилятор обычно делает
sizeof(int)
пространство для b
b
в космосfunc
можно изменить локальную копию b
не влияя на оригинал b
Это необходимо, поскольку, если он автоматически доставляется «ByRef», компилятор столкнется с проблемой, когда будет задано не L-значение, т. Е. 1, поскольку вы не можете получить ссылку из константного значения.
Теперь давайте посмотрим, что происходит с c
, Опять же, он имеет тип int*
не int&
таким образом, он рассматривается так же, как int b
,
Однако когда c
это int*
указатель, он не хранит никаких других данных, кроме адрес к некоторому объекту с типом int
. Таким образом, косвенный доступ через указатель разрешен, и существует только копия адрес но не значение, на которое оно указывает, поэтому может быть повреждено.
Я всегда предполагал, что передача переменных с [передачей по значению] в
[c ++], делает их копию, и поэтому функция, получающая эти
копии не могут изменить содержимое исходной переменной.
Да, это правда.
Я думаю, это потому, что когда аргумент передается по значению,
[copy-constructor] вызывается, и если он не переопределен
программист, по умолчанию [copy-constructor] делает [shallow-copy] вместо
[глубокая копия]!
Копия» является «мелкая копия». «Копия» копирует все содержимое объектов. И содержимое поля. И если поле является указателем, то содержимое является указателем, адресом. Вот и все.
Так что мой вопрос заключается в том, почему они назвали это по стоимости, а в
В случае наличия указателей в классе, функция имеет доступ к
ссылка на этот указатель и может повредить его.
Так? То, на что указывают эти указатели, не является частью объекта. Так что это не имеет значения. Указатель является частью объекта.