Зачем вам брать копию объекта в качестве параметра вашей функции? Почему const ref не является стандартным способом параметров? - PullRequest
3 голосов
/ 04 марта 2020

Как бы мне ни нравилось программирование на C ++, есть одна вещь, которую я действительно не понимаю. Мне кажется, что наиболее распространенный способ программирования функции такой:

some_function(a variable)
    do something according to the data in the variable

пример:

bool match_name(const std::string& name)
{
    return this->name == name;
}

Я использую const ref для 90% всей функции параметры в моем коде (возможно, я делаю что-то не так).

Мой вопрос: почему копия переменной является типом параметров по умолчанию? Почему const ref не используется по умолчанию?

Почему не что-то вроде?:

void my_function(My_type object)      // <- const ref

void my_function(ref My_type object)  // <- ref (mutable)

void my_function(copy My_type object) // <- copy

Ответы [ 2 ]

5 голосов
/ 04 марта 2020

Помимо исторических причин, это может иметь очень неприятные последствия. В основном это означает, что MyType myVarName будет иметь различное значение, когда находится область действия функции или когда используется в списке аргументов функции.

void foo(MyType myVar) //myVar is const ref
{
    MyType anotherVar = myVar; // anotherVar is a copy, what?
    const MyType& myVarRef = myVar; //a reference, but it looks like it has different type than myVar?
}

И подумайте о бедном &! Если вы не предложите другой способ отличить ссылки от не-ссылок, вы получите

void foo(MyType& myVar) //myVar is a copy?
{
    MyType& anotherVar = myVar; // anotherVar is a reference???
}

C ++ имеет хорошо установленное понятие об объекте и ссылку на объект. Последний всегда обозначается добавлением & к типу. Ваше предложение испортит это, и C ++ будет еще сложнее понять, чем сейчас.

3 голосов
/ 04 марта 2020

C ++ хочет быть совместимым с C, а поскольку C по умолчанию использует семантику значений, то же самое относится и к C ++. Было бы очень непоследовательным принимать встроенные типы по значению, но другие типы по ссылке.

Однако передача по ссылке не всегда лучше. Как правило, косвенное обращение к указателю приводит к тому, что компилятору становится труднее оптимизировать код gen. Во многих случаях передача типа по значению все же лучше, чем по ссылке. Это зависит от типа. Переадресация указателей на ссылки может вызвать чтение памяти, а передача по значению позволяет передавать объект в регистры процессора. Например, такой тип:

class Point {
public:
    /* functions */
private:
    int x;
    int y;
};

Всегда должен передаваться по значению. Это просто два целых числа. Ссылка может привести к тому, что ненужные чтения из памяти получат значения.

Кроме того, иногда требуется передать по значению, даже если тип не может быть зарегистрирован. Так называемые «функции приемника», например, которые должны хранить переданное значение, лучше работают со значениями благодаря семантике перемещения. Основные примеры - это constructros и setters:

void SomeClass::setString(std::string s)
{
    this->s_ = std::move(s);
}

Передача по ссылке в этом случае может привести к дополнительным копиям. Вы можете прочитать больше об этом онлайн. Хорошей отправной точкой является следующий вопрос:

Являются ли дни передачи const std :: string & в качестве параметра более?

...