C++ не имеет той же семантики, что и Java, для значений и ссылок. Сначала каждый тип может быть передан либо копией, либо ссылкой или по адресу (однако вы можете предотвратить передачу типов копиями путем скрытия конструктора копирования).
Проходной тип, наиболее тесно связанный с передачей «по ссылке» Java, является указателем. Вот пример из трех:
void foo(std::string bar); // by copy
void foo(std::string& bar); // by reference
void foo(std::string* bar); // by address
Как примечание стороны, проходя мимо копии всегда дороже, чем передача по ссылке или указателю для типов, которые больше, чем размер указателя. По этой причине вы также можете часто ссылаться на ссылку const
, что позволит вам читать объект без необходимости его копирования.
void foo(const std::string& bar); // by const reference
Однако, это все сложно, и вы должны быть осведомлены о Java тонкостях правильно, что вы хотите в C++ решить. В Java вы фактически не передаете объекты по ссылкам: вы передаете ссылки на объекты по копии. То есть, если вы назначаете новый объект аргументу, объект родительской области не изменится. В C++ это более близко соответствует прохождению объектов по адресу, чем по ссылке. Вот пример того, как это важно:
// Java using "object references":
public static void foo(String bar)
{
bar = "hello world";
}
public static void main(String[] argv)
{
String bar = "goodbye world";
foo(bar);
System.out.println(bar); // prints "goodbye world"
}
// C++ using "references":
void foo(std::string& bar)
{
bar = "hello world";
}
int main()
{
std::string bar = "goodbye world";
foo(bar);
std::cout << bar << std::endl; // prints "hello world"
}
// C++ using pointers:
void foo(std::string* bar)
{
bar = new std::string("goodbye world");
delete bar; // you don't want to leak
}
int main()
{
std::string bar = "goodbye world";
foo(&bar);
std::cout << bar << std::endl; // prints "hello world"
}
Другими словами, при использовании ссылки на C++, вы действительно имеем дело с же переменной вы прошли.Любые изменения, которые вы делаете с ним, даже присваивания, отражаются в родительской области. (Отчасти это связано с тем, как C++ имеет дело с оператором присваивания.) Используя указатели, вы получаете более тесное отношение к тому, которое у вас есть с ссылками Java, за счет того, что возможно получить адреса объектов через унарный оператор &
(см. foo(&bar)
в моем примере), необходимо использовать оператора ->
для доступа к элементам и некоторую дополнительную сложность для использования перегрузок операторов.
Другая заметная разница заключается в том, что, поскольку использование аргументов by-reference синтаксически тесно связано с использованием аргументов by-copy, функции должны иметь возможность предположить, что объекты, которые вы передаете по ссылке, действительны. Несмотря на то, что обычно можно передать ссылку на NULL
, это очень сильно обескураживает, так как единственный способ сделать это - разыменовать NULL
, который имеет неопределенное поведение. Поэтому, если вам нужно передать NULL
в качестве параметра, вы предпочитаете передавать аргументы по адресу, а не по ссылке.
В большинстве случаев вы захотите перейти по ссылке вместо адреса, если хотите изменить аргумент из функции, потому что он больше «C++ дружественный» (если вам не нужно значение NULL
), хотя это не совсем так, как это делает Java.
Это домашнее задание? Вероятно, вы захотите ознакомиться с операторами C * (косвенное) и & (ссылкой). – eggyal
@eggyal Ни C, ни C++ не имеют ссылочного оператора - & является адресом оператора. –
@unapersson: какая разница? : s – eggyal