Скрытые функции C++? [закрытый]

114
задан 5 revs, 4 users 100% 9 September 2009 в 23:44
поделиться

50 ответов

Большинство программистов на C++ знакомо с тернарным оператором:

x = (y < 0) ? 10 : 20;

Однако они не понимают, что это может использоваться в качестве lvalue:

(a == 0 ? a : b) = 1;

, который является стенографией для

if (a == 0)
    a = 1;
else
    b = 1;

Использование с осторожностью:-)

308
ответ дан 2 revs 24 November 2019 в 02:28
поделиться

Можно поместить URIs в источник C++ без ошибки. Например:

void foo() {
    http://stackoverflow.com/
    int bar = 4;

    ...
}
239
ответ дан Ben 24 November 2019 в 02:28
поделиться

Адресная арифметика с указателями.

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

самый прохладный C++ я когда-либо видел хотя? Аналоговые литералы.

140
ответ дан 3 revs, 3 users 88%Anonymouse 24 November 2019 в 02:28
поделиться

Я соглашаюсь с большинством сообщений там: C++ является языком мультипарадигмы, таким образом, "скрытыми" функциями, которые Вы найдете (кроме "неопределенных поведений", которых необходимо избежать по всей стоимости) является умное использование средств.

большинство тех средств не является сборкой - в функциях языка, но основанных на библиотеке.

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

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

самая известная из "скрытой" функции C++ шаблонное метапрограммирование , поскольку это позволяет Вам иметь свою программу частично (или полностью) выполняемый во время компиляции вместо времени выполнения. Это трудно, тем не менее, и у Вас должно быть твердое схватывание на шаблонах прежде, чем попробовать его.

Другой делать использование нескольких парадигмой для создания "способов запрограммировать" за пределами предка C++, то есть, C.

При помощи [1 124] функторы , можно моделировать функции с дополнительной безопасностью типов и быть с сохранением информации. Используя шаблон команды , можно задержать выполнение кода. Большинство другой шаблоны разработки могут быть легко и эффективно реализованы в C++ для создания альтернативных стилей кодирования, которые, как не предполагают, были в списке "официальных парадигм C++".

При помощи [1 127] шаблоны , можно произвести код, который будет работать над большинством типов, включая не тот, который Вы думали сначала. Можно увеличить безопасность типов, также (как автоматизированный безопасный с точки зрения типов malloc/realloc/free). Функции объекта C++ действительно мощны (и таким образом, опасны, если используется небрежно), но даже динамический полиморфизм имеет свою статическую версию в C++: CRTP.

я нашел, что большинство" Эффективный C++ " - вводит книги от Scott Meyers или" Исключительный C++ " - книги типа от Herb Sutter, чтобы быть и легким читать, и вполне сокровища информации об известных и менее известных функциях C++.

Среди моего предпочтительного тот, который должен сделать волосы из любого повышения программиста Java от ужаса: В C++ самым объектно-ориентированным способом добавить опцию к объекту является через недруга лица, не являющегося членом какой-либо организации, функция, вместо функции членства (т.е. метод класса), потому что:

  • В C++, интерфейс класса является и своими функциями членства и функциями лица, не являющегося членом какой-либо организации, в том же недруге пространства имен

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

Это удивляет даже опытных разработчиков.

(Источник: Среди других, Гуру Herb Sutter онлайн Недели № 84: http://www.gotw.ca/gotw/084.htm )

119
ответ дан 6 revs, 3 users 93% 24 November 2019 в 02:28
поделиться

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

namespace fs = boost::filesystem;

fs::path myPath( strPath, fs::native );
118
ответ дан Jason Mock 24 November 2019 в 02:28
поделиться

Оператор массива ассоциативен.

А [8] является синонимом для * (+ 8). Так как дополнение ассоциативно, который может быть переписан как * (8 + A), который является синонимом для..... 8

Вы не сказали полезный...:-)

77
ответ дан Colin Jensen 24 November 2019 в 02:28
поделиться

Одна вещь это мало известно, состоит в том, что объединения могут быть шаблонами также:

template<typename From, typename To>
union union_cast {
    From from;
    To   to;

    union_cast(From from)
        :from(from) { }

    To getTo() const { return to; }
};

И у них могут быть конструкторы и функции членства также. Просто ничто, что имеет отношение к наследованию (включая виртуальные функции).

73
ответ дан 2 revs 24 November 2019 в 02:28
поделиться

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

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

72
ответ дан Konrad Rudolph 24 November 2019 в 02:28
поделиться

Время жизни временных файлов, связанных со ссылками константы, является тем, о котором знают немного людей. Или по крайней мере это - моя любимая часть знания C++, что большинство людей не знает о.

const MyClass& x = MyClass(); // temporary exists as long as x is in scope
61
ответ дан 3 revs, 3 users 57% 24 November 2019 в 02:28
поделиться

Хорошей функцией, которая не используется часто, является блок try-catch всей функции:

int Function()
try
{
   // do something here
   return 42;
}
catch(...)
{
   return -1;
}

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

52
ответ дан vividos 24 November 2019 в 02:28
поделиться

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

if(int * p = getPointer()) {
    // do something
}

Некоторое использование макросов, что, например, для обеспечения некоторого "заблокированного" объема как это:

struct MutexLocker { 
    MutexLocker(Mutex&);
    ~MutexLocker(); 
    operator bool() const { return false; } 
private:
    Mutex &m;
};

#define locked(mutex) if(MutexLocker const& lock = MutexLocker(mutex)) {} else 

void someCriticalPath() {
    locked(myLocker) { /* ... */ }
}

Также BOOST_FOREACH использует его под капотом. Для завершения этого это не только возможно в если, но также и в переключателе:

switch(int value = getIt()) {
    // ...
}

и в некоторое время цикле:

while(SomeThing t = getSomeThing()) {
    // ...
}

(и также в для условия). Но я не слишком уверен, являются ли они всем этим полезным:)

43
ответ дан 3 revs 24 November 2019 в 02:28
поделиться

Инициализация массива в конструкторе. Например, в классе, если у нас есть массив int как:

class clName
{
  clName();
  int a[10];
};

Мы можем инициализировать все элементы в массиве к его значению по умолчанию (здесь все элементы массива для обнуления) в конструкторе как:

clName::clName() : a()
{
}
28
ответ дан 3 revs, 3 users 65% 24 November 2019 в 02:28
поделиться

Считайте файл в вектор строк:

 vector<string> V;
 copy(istream_iterator<string>(cin), istream_iterator<string>(),
     back_inserter(V));

istream_iterator

17
ответ дан Jason Baker 24 November 2019 в 02:28
поделиться

Скрытые функции:

  1. Чистые виртуальные функции могут иметь реализацию. Типичный пример, чистый виртуальный деструктор.
  2. , Если функция выдает исключение, не перечисленное в его спецификациях исключения, но функция имеет std::bad_exception в его спецификации исключения, исключение преобразовывается в std::bad_exception и выдается автоматически. Тем путем Вы будете, по крайней мере, знать, что bad_exception был брошен. Read больше здесь .

  3. функция пробуют блоки

  4. шаблонное ключевое слово в устранении неоднозначности определений типов в шаблоне класса. Если название членской шаблонной специализации появляется после ., ->, или :: оператор и то имя явно квалифицировали шаблонные параметры, снабдите префиксом членское шаблонное имя шаблон ключевого слова. Read больше здесь .

  5. значения по умолчанию параметра функции могут быть изменены во времени выполнения. Read больше здесь .

  6. A[i] работы, столь же хорошие как i[A]

  7. , Временные экземпляры класса могут быть изменены! Функция членства неконстанты может быть вызвана на временный объект. Например:

    struct Bar {
      void modify() {}
    }
    int main (void) {
      Bar().modify();   /* non-const function invoked on a temporary. */
    }
    

    Read больше здесь .

  8. , Если два различных типов присутствуют прежде и после : в троичном выражении оператора (?:), то получающийся тип выражения является тем, который является самым общим из двух. Например:

    void foo (int) {}
    void foo (double) {}
    struct X {
      X (double d = 0.0) {}
    };
    void foo (X) {} 
    
    int main(void) {
      int i = 1;
      foo(i ? 0 : 0.0); // calls foo(double)
      X x;
      foo(i ? 0.0 : x);  // calls foo(X)
    }
    
26
ответ дан 5 revs, 3 users 64% 24 November 2019 в 02:28
поделиться

map::operator[] создает запись, если ключ пропускает и возвращает ссылку на созданное из значения по умолчанию входное значение. Таким образом, можно записать:

map<int, string> m;
string& s = m[42]; // no need for map::find()
if (s.empty()) { // assuming we never store empty values in m
  s.assign(...);
}
cout << s;

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

24
ответ дан Constantin 24 November 2019 в 02:28
поделиться

Помещение функций или переменных в неназванном пространстве имен удерживает от использования использование static для ограничения их объемом файла.

20
ответ дан Jim Hunziker 24 November 2019 в 02:28
поделиться

Для определения обычного друга функции в шаблонах классов нужно особое внимание:

template <typename T> 
class Creator { 
    friend void appear() {  // a new function ::appear(), but it doesn't 
        …                   // exist until Creator is instantiated 
    } 
};
Creator<void> miracle;  // ::appear() is created at this point 
Creator<double> oops;   // ERROR: ::appear() is created a second time! 

В этом примере, два различных инстанцирования создают два идентичных definitions— прямое нарушение ODR

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

template <typename T> 
class Creator { 
    friend void feed(Creator<T>*){  // every T generates a different 
        …                           // function ::feed() 
    } 
}; 

Creator<void> one;     // generates ::feed(Creator<void>*) 
Creator<double> two;   // generates ::feed(Creator<double>*) 

Правовая оговорка: Я вставил этот раздел от Шаблоны C++: полное руководство / Раздел 8.4

19
ответ дан Özgür 24 November 2019 в 02:28
поделиться

Oooh, я могу придумать список главных объектов неприязни вместо этого:

  • Деструкторы должны быть виртуальными, если Вы предназначаете использование полиморфно
  • Иногда, участники инициализируются по умолчанию, иногда они не
  • , Локальные классы не могут использоваться в качестве шаблонных параметров (делает их менее полезными)
  • спецификаторы исключения: выглядите полезными, но не
  • , функциональные перегрузки скрывают функции базового класса с различными подписями.
  • никакая полезная стандартизация на интернационализации (портативный стандартный широкий набор символов, кто-либо? Мы должны будем ожидать до C++ 0x)

Зато

  • скрытая функция: функционируйте блоки попытки. К сожалению, я не нашел использование для него. Да я знаю, почему они добавили его, но необходимо повторно бросить в конструктора, который делает его бессмысленным.
  • стоит посмотреть тщательно на гарантии STL о законности итератора после контейнерной модификации, которая может позволить Вам сделать некоторые немного более хорошие циклы.
  • Повышение - это - едва секрет, но это стоит использовать.
  • оптимизация Возвращаемого значения (не очевидный, но это конкретно позволяется стандартом)
  • Функторы иначе функциональные объекты иначе оператор (). Это используется экстенсивно STL. не действительно секрет, но изящный побочный эффект перегрузки оператора и шаблонов.
27
ответ дан 3 revs 24 November 2019 в 02:28
поделиться

Одна из самых интересных грамматик любых языков программирования.

Три из этих вещей принадлежат вместе, и два что-то в целом различное...

SomeType t = u;
SomeType t(u);
SomeType t();
SomeType t;
SomeType t(SomeType(u));

Все кроме третьего и пятого определяют SomeType объект на стеке и инициализируют его (с u в первых двух случаях и конструкторе по умолчанию в четвертом. Третье объявляет функцию, которая не берет параметров и возвращается SomeType. Пятое так же объявляет функцию, которая берет один параметр значением типа SomeType, названного u.

14
ответ дан 2 revs, 2 users 80% 24 November 2019 в 02:28
поделиться

Избавление от предописаний:

struct global
{
     void main()
     {
           a = 1;
           b();
     }
     int a;
     void b(){}
}
singleton;

операторы переключения Записи с?: операторы:

string result = 
    a==0 ? "zero" :
    a==1 ? "one" :
    a==2 ? "two" :
    0;

Выполнение всего на одной строке:

void a();
int b();
float c = (a(),b(),1.0f);

структуры Обнуления без memset:

FStruct s = {0};

угол Нормализации/обертывания - и временные стоимости:

int angle = (short)((+180+30)*65536/360) * 360/65536; //==-150

Присваивающиеся ссылки:

struct ref
{
   int& r;
   ref(int& r):r(r){}
};
int b;
ref a(b);
int c;
*(int**)&a = &c;
12
ответ дан 3 revs 24 November 2019 в 02:28
поделиться

Не только переменные могут быть объявлен в части init цикла for , а также классы и функции.

for(struct { int a; float b; } loop = { 1, 2 }; ...; ...) {
    ...
}

Это позволяет использовать несколько переменных разных типов.

102
ответ дан 24 November 2019 в 02:28
поделиться

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

Обычно C ++ запрещает вам доступ к нестатическим защищенным членам объекта класса, даже если этот класс является вашим базовым классом.

struct A {
protected:
    int a;
};

struct B : A {
    // error: can't access protected member
    static int get(A &x) { return x.a; }
};

struct C : A { };

Это запрещено: вы и компилятор не знаете, на что в действительности указывает ссылка. Это может быть объект C , и в этом случае класс B не имеет никакого отношения к своим данным. Такой доступ предоставляется, только если x является ссылкой на производный класс или производный от него. И он может позволить произвольному фрагменту кода читать любой защищенный член, просто создавая «одноразовый» класс, который считывает члены, например, std :: stack :

void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        static std::deque<int> &get(std::stack<int> &s) {
            // error: stack<int>::c is protected
            return s.c;
        }
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = pillager::get(s);
}

Конечно, как вы видите, это нанесет слишком большой урон. Но теперь указатели на элементы позволяют обойти эту защиту! Ключевым моментом является то, что тип указателя на член привязан к классу, который фактически содержит указанный член - , а не к классу, который вы указали при получении адреса. Это позволяет нам обойти проверку

struct A {
protected:
    int a;
};

struct B : A {
    // valid: *can* access protected member
    static int get(A &x) { return x.*(&B::a); }
};

struct C : A { };

И, конечно же, это также работает с примером std :: stack .

void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        static std::deque<int> &get(std::stack<int> &s) {
            return s.*(pillager::c);
        }
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = pillager::get(s);
}

Это будет еще проще с объявлением using в производном классе, которое делает имя члена общедоступным и ссылается на член базового класса.

void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        using std::stack<int>::c;
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = s.*(&pillager::c);
}
27
ответ дан 24 November 2019 в 02:28
поделиться

Многие знают о метафункции identity / id , но есть хороший вариант использования для не шаблонных случаев: Простота написания объявлений:

// void (*f)(); // same
id<void()>::type *f;

// void (*f(void(*p)()))(int); // same
id<void(int)>::type *f(id<void()>::type *p);

// int (*p)[2] = new int[10][2]; // same
id<int[2]>::type *p = new int[10][2];

// void (C::*p)(int) = 0; // same
id<void(int)>::type C::*p = 0;

Это очень помогает расшифровывать объявления C ++!

// boost::identity is pretty much the same
template<typename T> 
struct id { typedef T type; };
44
ответ дан 24 November 2019 в 02:28
поделиться

Вы можете использовать шаблоны битовых полей.

template <size_t X, size_t Y>
struct bitfield
{
    char left  : X;
    char right : Y;
};

Я еще не придумал какой-либо цели для этого, но это, черт возьми, меня удивило.

14
ответ дан 24 November 2019 в 02:28
поделиться

Один пример из многих: шаблонное метапрограммирование. Никто в комитете по стандартам не намеревался там быть полным по Тьюрингу подъязыком, который выполняется во время компиляции.

Шаблонное метапрограммирование является едва скрытой функцией. Это находится даже в библиотеке повышения. См. MPL. Но если "почти скрытый" достаточно хорошо, то смотрите на библиотеки повышения . Это содержит много конфет, которые не являются легки доступный без поддержки сильной библиотеки.

Один пример библиотека boost.lambda , которая интересна, так как C++ не имеет функций лямбды в текущем стандарте.

Другой пример Loki, который "делает широкое применение шаблонного метапрограммирования C++ и реализует несколько наиболее часто используемых инструментов: список типов, функтор, одиночный элемент, интеллектуальный указатель, возражает фабрике, посетителю и мультиметодам". [ Википедия ]

6
ответ дан 2 revs, 2 users 84% 24 November 2019 в 02:28
поделиться

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

На самом деле от достаточно простой конструкции языка можно записать что-то очень мощное. Много таких вещей доступно по www.boost.org как примеры (и http://www.boost.org/doc/libs/1_36_0/doc/html/lambda.html среди них).

Для понимания пути, как простой язык constuction может быть объединен к чему-то мощному, которое хорошо считать "Шаблоны C++: полное руководство" David Vandevoorde, Nicolai M. Josuttis и действительно волшебная книга "современный Дизайн C++..." Andrei Alexandrescu .

И наконец, трудно изучить C++, необходимо попытаться заполнить его;)

5
ответ дан sergtk 24 November 2019 в 02:28
поделиться

Я не уверен в скрытом, но существуют [приблизительно 110] интересные 'приемы' , которые, вероятно, не очевидны из просто чтения спецификации.

3
ответ дан dbrien 24 November 2019 в 02:28
поделиться

Большинство разработчиков C++ игнорирует питание шаблонного метапрограммирования. Выезд Loki Libary . Это реализует несколько усовершенствованных инструментов как список типов, функтор, одиночный элемент, интеллектуальный указатель, объектная фабрика, посетитель и шаблонное метапрограммирование использования мультиметодов экстенсивно (от Википедия ). Для большей части части Вы могли рассмотреть их как "скрытую" функцию C++.

3
ответ дан Sridhar Iyer 24 November 2019 в 02:28
поделиться
  • указатели на методы класса
  • ключевое слово
"имени типа"
3
ответ дан shoosh 24 November 2019 в 02:28
поделиться

Существует большое "неопределенное поведение". Можно изучить, как избежать их читающий хорошие книги и читающий стандарты.

3
ответ дан 2 revs, 2 users 50% 24 November 2019 в 02:28
поделиться