Все в C++ по умолчанию передается по значению

В C++ все типы передаются по значению, если они не идут с & или же * условное обозначение?

Например, в Java передача массива в качестве аргумента функции будет по умолчанию передаваться по ссылке. C++ дает вам больше контроля над этим?

РЕДАКТИРОВАТЬ: Спасибо за все ваши ответы, я думаю, что я понимаю, что все значение по передаче более ясно. Для тех, кто все еще не понимает, как Java передается по значению (копия ссылки на объект), этот ответ действительно прояснил его для меня.

2 ответа

Решение

В C++ все типы передаются по значению, если они не идут с символом & или *?

Нет, если вы передаете что-то как * параметр (его указатель), это все равно передается по значению. Копия переданного указателя сделана. Но и оригинал, и копия указывают на одну и ту же память. Это аналогичная концепция в C# - я верю и в Java, просто вы не используете * там.

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

Но если вы просто скажете назначить новое значение указателю, с внешним объектом ничего не произойдет. например

void foo(int* ptr)
{
  // ...
  // Below, nothing happens to original object to which ptr was 
  // pointing, before function call, just ptr - the copy of original pointer - 
  // now points to a different object 
  ptr = &someObj; 
  // ...
}

Например, в Java передача массива в качестве аргумента функции будет по умолчанию передаваться по ссылке. C++ дает вам больше контроля над этим?

В C++ или C, если вы передаете массив (например, int arr[]), то, что передается, обрабатывается как указатель на первый элемент массива. Следовательно, то, что я сказал выше, верно и в этом случае.

О & вы правы. Вы можете даже применить & к указателям (например, int *&), и в этом случае указатель действительно передается по ссылке - копия не создается.

Вероятно, касательно вашего вопроса, но я часто выбираю другое направление, чтобы понять, что происходит, когда вы вызываете функцию в C++.

Разница между

void foo(Bar bar);  // [1]
void foo(Bar& bar); // [2]
void foo(Bar* bar); // [3]

это тело в [1] получит копию оригинальной панели (мы называем это по значению, но я предпочитаю думать о ней как о своей собственной копии).

Тело [2] будет работать с точно таким же bar объект; нет копий. Можем ли мы изменить это bar Объект зависит от того, был ли аргумент Bar& bar (как показано на рисунке) или const Bar& bar, Обратите внимание, что в правильно сформированной программе[2] всегда получит объект (нет null Рекомендации; давайте оставим висячие ссылки в стороне).

Тело [3] получит копию указателя на оригинал bar, Могу ли я изменить указатель и / или указываемый объект, зависит от того, был ли аргумент const Bar* bar, const Bar* const bar, Bar* const bar, или же Bar* bar (Да, действительно). Указатель может или не может быть null,

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

struct Foo {
 std::shared_ptr<FooImpl> m_pimpl; 
};

по умолчанию будет иметь то же "содержимое", что и исходный (новый общий указатель, указывающий на то же FooImpl указатель). Это, конечно, зависит от того, как программист спроектировал класс.

По этой причине я предпочитаю думать о [1] как "берет копию бара", и если мне нужно узнать, будет ли такая копия тем, что я хочу и что мне нужно, я пойду и изучу класс напрямую, чтобы понять, что именно этот класс означает в частности под копией.

Другие вопросы по тегам