Каковы некоторые связанные с C++ идиомы, неправильные представления и глюки, которые Вы извлекли из опыта?

27
задан skaffman 18 February 2012 в 12:58
поделиться

13 ответов

Мне понравилось это со времени, я обнаружил его в некотором коде:

assert(condition || !"Something has gone wrong!");

или если у Вас нет условия под рукой, можно просто сделать

assert(!"Something has gone wrong!");

, следующее приписывается @Josh (см. комментарии). Это использует оператор запятой вместо этого:

assert(("Something has gone wrong!", condition)); 
18
ответ дан Community 28 November 2019 в 04:01
поделиться

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

#include <iostream>
using namespace std;

int& strangeFunction(int& x){return x;}


int main(){
        int a=0;
        strangeFunction(a) = 5;               //<------- I found this very confusing
        cout << a <<endl;
        return 0;
}
0
ответ дан Lucas 28 November 2019 в 04:01
поделиться

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

, Если Вы знаете размер в компиляции его простое. Даже если Вы знаете один из размеров во время компиляции. Если Вы просто не знаете..., что Вы могли бы смотреть на что-то вроде этого

m[i*dim2+j]

Являющийся i итератор для строк, dim2 количество седел и j итератор для седел

0
ответ дан AntonioCS 28 November 2019 в 04:01
поделиться

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

  • Конструктор по умолчанию
  • Конструктор Копии
  • Оператор присваивания

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

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

Это будет экономить Вам время в будущем.

3
ответ дан JaredPar 28 November 2019 в 04:01
поделиться

Так как я узнал о RAII (один из худших акронимов когда-либо) и интеллектуальный указатель, утечки памяти и утечки ресурсов почти полностью исчезли.

4
ответ дан Ferruccio 28 November 2019 в 04:01
поделиться

Так как мы все игнорируем OP и вместо этого отправляем наши любимые прохладные приемы...

повышение Использования (или tr1) shared_ptr для поддержания инварианта класса во времени выполнения (довольно очевидный, но я не видел, что кто-либо еще делает это):

#include <cassert>
#include <functional>
#include <stdexcept>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost;

class Foo
{
public:
    Foo() : even(0)
    {
        // Check on start up...
        Invariant();
    }

    void BrokenFunc()
    {
        // ...and on exit from public non-const member functions.
        // Any more is wasteful.
        shared_ptr<Foo> checker(this, mem_fun(&Foo::Invariant));

        even += 1;
        throw runtime_error("didn't expect this!");
        even += 1;
    }

private:
    void Invariant() { assert(even % 2 == 0); }
    int even;
};
5
ответ дан fizzer 28 November 2019 в 04:01
поделиться

Несколько вещей, которые обычно сбивают людей с толку:

std::cout << a << a++ << --a;
i = ++i;

вышеупомянутые строки оба не определены.

void foo(bar* b1, bar* b2);

int main() {
  foo(shared_ptr<bar>(new bar()), shared_ptr<bar>(new bar()));
}

Вышеупомянутое может пропустить память.

int* arr = new int[10];
arr + 11;

Это приводит к неопределенному поведению.

Что касается идиом, мой фаворит RAII. Выделите объекты на стеке, который гарантирует, что деструктор называют, когда объект выходит из объема, предотвращая утечки ресурсов.

5
ответ дан jalf 28 November 2019 в 04:01
поделиться

Можно часто скрывать путь больше материала в исходных файлах, чем Вы думаете. Не делайте все частным, если Вы не имеете к - часто лучше оставить его в анонимном пространстве имен в исходном файле. Это на самом деле делает вещи легче обработать, я нахожу, потому что тогда Вы не показываете детали реализации, все же вдохновлены сделать много из крошечных функций, а не монолитных.

6
ответ дан coppro 28 November 2019 в 04:01
поделиться

Одна редко используемая, но удобная идиома C++ является использованием?: оператор во время цепочки конструктора.

class Sample
{  
    const char * ptr;
    const bool  freeable;

    Sample(const char * optional):
        ptr( optional ? optional : new char [32]),
        freeable( optional ? false : true ) {}
    ~Sample( )  { if (freeable) delete[] ptr; }
}  

C++ не позволяет значениям константы быть измененными в теле конструктора, таким образом, это избегает бросков константы.

7
ответ дан Procedural Throwback 28 November 2019 в 04:01
поделиться

Иногда, заголовки загрязнены не ведущими себя макро-именами как

#define max(a, b) (a > b ? a : b)

, Который представит код, недопустимый, который использует макс. функциональный или функциональный объект, названный тем путем. Печально известный пример windows.h, который делает точно это. Один путь вокруг этого помещает круглые скобки вокруг вызова, который мешает ему использовать макрос и заставляет его использовать реальную макс. функцию:

void myfunction() {
    ....
    (max)(c, d);
}

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

11
ответ дан Johannes Schaub - litb 28 November 2019 в 04:01
поделиться

Никогда не напрасно тратьте время при попытке реализовать операции копии на классах, когда мы не знаем, будет ли она требоваться позже. Много объектов, которые мы обрабатываем, являются просто объектами, и копирование их едва имеет любой смысл. Сделайте их non-copyable и реализуйте копию/дублирование позже, если потребность действительно возникает.

14
ответ дан Luc Hermitte 28 November 2019 в 04:01
поделиться

Вот другой, я поймал однажды:

char int2hex(int x) {
     return "-0123456789abcdef"[(x >= 0 && x < 16) ? (x + 1) : 0];
}

это просто индексирует массив символов вместо того, чтобы делать переключатель. Если это вне диапазона, это возвращает '-'.

18
ответ дан Johannes Schaub - litb 28 November 2019 в 04:01
поделиться

Вы не должны знать сложный функциональный синтаксис объявления определения типа C++. Вот милый прием, который я нашел.

Быстрый, опишите это определение типа:

typedef C &(__cdecl C::* const CB )(const C &) const;

Легкий! CB является указателем на функцию членства класса C, принимающего ссылку константы на объект C и возвращающего ссылку неконстанты на объект C. О, и it’s функция членства константы. О, и сам указатель функции является const†¦ (Право?)

синтаксис спецификации объявления функции C++ является известно тупым и твердым помнить. Да, существуют приемы, которые закаленные ветераны C++ могут использовать для дешифровки таких ужасов, но that’s не, о чем эта подсказка. Эта подсказка о том, как Вы, don’t должен помнить этот ужасный синтаксис и все еще быть в состоянии объявить такие определения типов указателя функции (например, в случае, если you’re, взаимодействующий с некоторым API прежней версии, который никогда не слышал о повышении:: функция). Вместо того, чтобы повредить умственный пот, позвольте компилятору сделать работу для Вас. В следующий раз you’re пытающийся создать определение типа к функции членства, которая похожа на это:

struct C {
        const C& Callback(const C&) const   { }
};

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

, Например:

char c = &C::Callback;

компилятор счастливо извергает это полезное сообщение об ошибке:

“… cannot convert from 'const C &(__cdecl C::* )(const C &) const' to 'char'”

, Который является что поиск we’re.:)

55
ответ дан Jonathan Leffler 28 November 2019 в 04:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: