Порядок аргументов для смешанной константной и неконстантной передачи по ссылке - PullRequest
3 голосов
/ 24 февраля 2010

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

void auxiliaryFunction(
        const Class& c,
        std::vector< double >& out);

Его цель - сделать что-то с открытыми функциями-членами c и заполнить вектор выводом. Вы можете заметить, что порядок аргументов напоминает порядок функций-членов Python, def auxiliaryFunction(self, out).

Однако есть и другие разумные способы выбора порядка аргументов: можно сказать, что эта функция напоминает операцию присваивания, out = auxiliaryFunction(c). Эта идиома используется, например, в

char* strcpy ( char* destination, const char* source );

Что если у меня есть другая функция, которая не напоминает несущественную функцию-член, то есть ту, которая инициализирует новый объект, который я создал:

void initializeMyObject(
    const double a,
    const std::vector<double>& b,
    MyObject& out);

Итак, для согласованности, я должен использовать тот же порядок (последняя изменяемая переменная), что и в auxiliaryFunction?

В общем, лучше выбрать (non-const , const) вместо (const, non-const) или только в определенных ситуациях? Есть ли какие-то причины для выбора, или я должен просто выбрать один и придерживаться его?

(Кстати, мне известно о руководстве по стилю Google , в котором предлагается использовать указатели вместо неконстантных ссылок, но это касается моего вопроса.)

Ответы [ 2 ]

4 голосов
/ 24 февраля 2010

Алгоритмы STL помещают выходные (неконстантные) значения в последнюю очередь. Там у вас есть прецедент для C ++, о котором все должны знать.

Я также склонен упорядочивать аргументы от важных до менее важных. (т. е. размер блока идет до значения настройки поля бокса.)

(Обратите внимание: что бы вы ни делали, будьте последовательны! Это бесконечно важнее, чем выбирать тот или иной путь ...)

1 голос
/ 24 февраля 2010

Несколько пунктов, которые могут быть полезны:

  • Да, мне нравится идея как можно больше следовать соглашению о порядке аргументов стандартной библиотеки. Принцип наименьших сюрпризов. Итак, хорошо идти. Однако помните, что сама стандартная библиотека C не очень хорошо разработана, особенно если вы посмотрите на API обработки файлов. Так что будьте осторожны - учитесь на этих ошибках.

  • const с базовыми арифметическими типами используются редко, если вы это сделаете, это будет большим сюрпризом.

  • STL, даже с его недостатками, является лучшим примером для ИМО.

  • Наконец, обратите внимание, что в C ++ есть еще одно преимущество, называемое оптимизацией возвращаемого значения, которое по умолчанию включено в большинстве современных компиляторов. Я бы использовал это и переписал бы ваш initializeMyObject или даже лучше, использовал бы класс и конструкторы.

  • Передача по константной ссылке, а не по значению - экономит много времени на копирование (как время, так и потери памяти)

Итак, ваша подпись функции должна выглядеть примерно так:

 MyObject initializeMyObject(
    double a,
    const std::vector<double>& b,
    );

(И у меня может возникнуть искушение скрыть std::vector<double> на typedef, если это возможно.)

В общем, лучше ли выбирать (неконстантный, константный), чем (константный, неконстантный) или только в определенных ситуациях? Есть ли какие-либо причины для выбора одного или я должен просто выбрать один и придерживаться его?

Используйте либеральную дозу const всякий раз, когда можете. Для параметров, для функций. Вы даете обещание компилятору (чтобы оно соответствовало вашему замыслу), и компилятор будет помогать вам каждый раз, когда вы отвлекаетесь от диагностики. Сделайте большую часть ваших языковых возможностей и компиляторов. Кроме того, узнайте о const& (const-ссылки) и их потенциальных преимуществах производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...