Копируя указатель, измените то, на что указывает копия, не меняя оригинал? - PullRequest
0 голосов
/ 07 апреля 2019

Можно ли скопировать указатель, а затем изменить значение, на которое он указывает, без изменения исходного указателя?

Например, скажем, у меня было следующее:

int *i;
auto j = i;

*j = new_val;

Это изменит значение, сохраненное по адресу, на который указывает i, потому что и i, и j указываютна тот же адрес памяти, который я не хочу.

Поскольку этот пример очень прост, я мог бы просто создать новый int *j, не копируя i.Но в более сложных случаях, таких как связанный список, я бы не хотел воссоздавать связанный список.

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

1 Ответ

2 голосов
/ 07 апреля 2019

Сначала некоторые уточнения.Указатель - это автономная переменная , которая содержит адрес памяти.Ни больше ни меньше.Тип poitner означает, что вы, программист, сообщили компилятору, что хранится по этому адресу, чтобы вы могли извлечь значение, хранящееся по этому адресу - это называется разыменованием.

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

std::unique_ptr<int> i = std::make_unique<int>(10); 
//Here we created a variable on the heap and gave it a value 10,
//the address of it is stored in **i**

std::unique_ptr<int> j = std::make_unique<int>(*i);
//Here we created a variable on the heap nad gave it a value
//stored at the address in **i**. Notice the dereferencing
//that means we want to copy the value pointed to,
//not the pointer itself.

Теперь без умных указателей, если это сделает большесмысл для вас:

int *i = new int(10);
int *j = new int(*i);
delete i;
delete j;

Это делает то же самое, но вам нужно управлять памятью самостоятельно, и она будет просачиваться, например, при возникновении исключения.

Теперь это будет работать для всехтипы, которые являются тривиальными, например int в примере, или типы, для которых определен конструктор копирования.Компилятор обычно генерирует один для ваших типов автоматически, если только по какой-то причине он не может этого сделать, в этом случае вам придется предоставить его самостоятельно:

Подробнее см. Здесь: Копировать конструкторы

РЕДАКТИРОВАТЬ: Некоторые очень хорошие объяснения указателей, включая демонстрацию того, как делать то, что вы хотите сделать: Указатели C ++ от TheCherno

...