У меня есть другая перспектива ответить на это.
При работе на разных уровнях, например, в приложении MVC, контроллеру нужны службы для вызова бизнес-операций. В таких сценариях контейнер инжекции зависимостей может использоваться для инициализации служб, чтобы исключить исключение NullReferenceException. Это означает, что вам не нужно беспокоиться о проверке нулевого значения и просто вызвать службы с контроллера, как будто они всегда будут доступны (и инициализированы) как одиночный или прототип.
public class MyController
{
private ServiceA serviceA;
private ServiceB serviceB;
public MyController(ServiceA serviceA, ServiceB serviceB)
{
this.serviceA = serviceA;
this.serviceB = serviceB;
}
public void MyMethod()
{
// We don't need to check null because the dependency injection container
// injects it, provided you took care of bootstrapping it.
var someObject = serviceA.DoThis();
}
}
Вам нужна помощь в понимании разницы?
Представьте себе вызывающую функцию в первом случае:
IntElement *head;
int data;
...
insertInFront (head, data);
Теперь в этом случае адрес, на который указывает голова, помещается в стек и передается как аргумент для insertInFront. Когда insertInFront делает head = newElement; изменяется только аргумент (в стеке).
Во втором случае вызывающий абонент будет:
IntElement *head;
int data;
...
insertInFront (&head, data);
В этом случае адрес головы помещается на стек и передается в качестве аргумента для insertInFront. Когда вы делаете * head = newElement, это переданное в адресе де-ссылку, чтобы получить адрес исходной главы списка, и это было изменено.
Его довольно просто, когда вы обнимаете то, что указатель. В первом коде IntElement *head
head является указателем на существующий заголовок связанного списка. Таким образом, вызывающий объект передается по адресу элемента заголовка списка. Изменение значения головки во вставке в переднюю функцию не изменяет ничего на вызывающем. Значение этого адреса было передано вашей функции, а не то, что удерживало этот адрес у вызывающего.
Вам нужно передать свою функцию «адрес адреса головы» - или IntElement **head
, Это позволит этой функции изменить адрес, удерживаемый вызывающим абонентом, т. Е. Обновить связанный список, чтобы указать на новую головку.
Где бы вы ни располагали значение T x
и вам нужна другая функция для его изменения, вы передаете указатель на x
:
T x; // set to some value
modify_me(&x); // will change x
/* ... */
void modify_me(T * x)
{
*x = new_value;
}
Теперь просто примените этот механизм к T = IntElement*
, Значения, которые вы хотите изменить, сами являются указателями!
(Возможно, использование typedef сделает вещи менее запутанными: typedef IntElement * NodePtr;
.)
Также обратите внимание, что ваш связанный список не работает потому что вы никогда не устанавливаете «следующий» указатель нового элемента на указатель на старую голову и аналогично для «предыдущего» указателя, если список дважды связан.
Вы не хотите изменять значения головных точек, вы хотите изменить указатель, который хранится в самой голове, поэтому не используйте * head, используйте указатель для самой головки. Голова имеет тип IntElement *
, поэтому параметр должен быть указателем на такой тип: IntElement **