Почему бы не перегрузить оператор + = () для std :: vector? - PullRequest
20 голосов
/ 16 июня 2011

Я начал изучать C ++, поэтому из-за недостатка знаний и опыта я не знаю, почему что-то столь простое для новичка, как то, что я собираюсь описать, уже отсутствует в STL.Чтобы добавить вектор к другому вектору, вы должны напечатать это:

v1.insert(v1.end(), v2.begin(), v2.end());

Мне интересно, могут ли в реальном мире просто перегрузить оператор + =, чтобы сделать это менее многословным, например, с эффектом

template <typename T>
void operator+=(std::vector<T> &v1, const std::vector<T> &v2) {
    v1.insert(v1.end(), v2.begin(), v2.end());
}

так что тогда вы можете

v1 += v2;

У меня также есть эта настройка для push_back для "+ =" одного элемента до конца.Есть ли какая-то причина, по которой эти вещи не следует делать или их избегают люди, хорошо владеющие C ++?

Ответы [ 4 ]

20 голосов
/ 16 июня 2011

Это на самом деле случай, когда я хотел бы видеть эту функциональность в виде перегрузки append(). operator+= довольно двусмысленно, вы хотите добавить элементы каждого вектора друг к другу? Или вы хотите добавить?

Однако, как я уже сказал, я бы приветствовал: v1.append(v2); Это ясно и просто, я не знаю, почему его там нет.

3 голосов
/ 16 июня 2011

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

Это означает, например, если нет математического определения произведениядва объекта, не перегружайте оператор умножения для этих объектов.Если имелось математическое соответствие, перегрузка операторов может сделать класс более удобным для использования, позволяя уравнениям выражаться в форме a * b + c, а не в более многословном (a.multiply (b)). Add (c) Гдеиспользуются операторы сложения и умножения, намерение - сложение и умножение.Любое другое значение более чем вероятно может смутить других.Некоторые другие типы, где допустима перегрузка операторов (и, на мой взгляд, предпочтительнее ), являются интеллектуальными указателями, итераторами, комплексными числами, векторами и бигнумами.

Это следует из одной схемыЦели C ++ заключаются в том, чтобы иметь возможность определять классы, которые так же просты в использовании, как и встроенные типы.Конечно, есть операторы, которые вы можете определить для классов, которые также не являются математическими понятиямиВы можете захотеть перегрузить операторы == и! = Вместо написания метода isEqual и, возможно, захотите перегрузить =, потому что оператор присваивания по умолчанию компилятора не тот, который вам нужен.

С другой стороны, перегрузка оператораОператор, делающий что-то неожиданное, например определение ^ для перевода строки на японский, неясен и опасен.Ваши коллеги-программисты не будут рады узнать, что то, что выглядело как эксклюзив или сравнение, на самом деле было совсем другим.Тогда решение состоит в том, чтобы написать свои классы, чтобы упростить написание clear и обслуживаемого кода, независимо от того, означает ли это перегрузку операторов или ее избежание.

Добавление двух векторовслишком двусмысленно, чтобы не определить оператора.Как показали другие, многие люди имеют разные представления о том, что это значит, в то время как для строки все понимают, что сложение двух строк означает конкатенацию.В вашем примере не совсем ясно, хотите ли вы добавить компонент для всех элементов, добавить элемент в конец или объединить два вектора вместе.Хотя это может быть более кратким, сделать это таким образом, использование перегрузки операторов для создания собственного языка программирования - не лучший способ.

* Да, я знаю, что Stroustrup перегружен << и >> делатьпотоковые операции, а не битовые сдвиги.Но они не часто использовались по сравнению с арифметическими и указательными операторами, во-первых, и можно утверждать, что теперь, когда все знают, как использовать cout, обычно понимают, что << и >> являются операторами вставки и извлечения.(Первоначально он пытался использовать только <и> для ввода и вывода, но значение этих операторов было настолько укоренилось в умах, что код стал нечитаемым.)

3 голосов
/ 16 июня 2011

Я думаю, что основная причина в том, что семантика += не очевидна.Здесь есть значение, которое у вас есть, но есть и одинаково допустимое значение, которое является поэлементным сложением каждого элемента векторов одинакового размера.Из-за этой неоднозначности я предполагаю, что они решили, что лучше положиться на пользователя, который будет звонить insert прямо.

2 голосов
/ 16 июня 2011

В дополнение к тому, что другие упоминали об этом синтаксисе, который не является интуитивно понятным и поэтому подвержен ошибкам, он также идет вразрез с хорошим правилом разработки, заключающимся в том, что общие алгоритмы применяются к различным свободным функциям контейнеров, а также к специальным алгоритмам контейнеров - функциям-членам. Большинство контейнеров следуют этому правилу, за исключением std::string, который получил много шума от Херба Саттера за его монолитный дизайн.

...