Я был ликующим для наблюдения пользы gKrellm для 12,04. Его не совсем столь же роскошный как окна 7 виджетов, но сделает почти весь одинаковый вещи.
Просто открывают центр программного обеспечения и ищут gkrellm.
я знаю, что у них есть погодный плагин, но afaik, там не проверка Твиттера.
Первый случай:
Display *disp = new Display();
Выполняет три действия:
disp
с типом Display *
, что является указателем на объект типа Display
, а затем Display
в куче, а disp
, чтобы указать на новый объект Display
. Во втором случае:
Display *disp; disp = new GzDisplay();
Вы создаете переменную disp
с типом Display *
, а затем создайте в куче объект другого типа , GzDisplay
и назначьте его указатель на переменную disp
.
Это будет только работать если GzDisplay является подклассом Display. В данном случае это выглядит как пример полиморфизма .
Кроме того, чтобы ответить на ваш комментарий, нет никакой разницы между объявлениями:
Display* disp;
и
Display *disp;
Однако из-за того, как работают правила типа C, есть разница между:
Display *disp1;
Display* disp2;
и
Display *disp1, disp2;
Потому что в последнем случае disp1
- это указатель на объект Display
, вероятно, размещенный в куче, тогда как disp2
является фактическим объектом, вероятно, размещенным в стеке. . То есть, хотя указатель, возможно, является частью типа, синтаксический анализатор вместо этого свяжет его с переменной.
disp2
является фактическим объектом, вероятно, размещенным в стеке. То есть, хотя указатель, возможно, является частью типа, синтаксический анализатор вместо этого свяжет его с переменной. вероятно, размещен в куче, тогда как disp2
является фактическим объектом, вероятно, размещенным в стеке. То есть, хотя указатель, возможно, является частью типа, синтаксический анализатор вместо этого свяжет его с переменной. // implicit form
// 1) creates Display instance on the heap (allocates memory and call constructor with no arguments)
// 2) creates disp variable on the stack initialized with pointer to Display's instance
Display *disp = new Display();
// explicit form
// 1) creates Display instance on the heap (allocates memory and call constructor with no arguments)
// 2) creates disp variable on the stack initialized with pointer to Display's instance
Display* disp(new Display());
// 1) creates uninitialized disp variable on the stack
// 2) creates Display instance on the heap (allocates memory and call constructor with no arguments)
// 3) assigns disp with pointer to Display's instance
Display *disp;
disp = new Display();
Разница между явной и неявной формами инициализации будет видна только для сложных типов с конструкторами. Для типа указателя (Display *) нет никакой разницы.
Чтобы увидеть разницу между явной и неявной формами, просмотрите следующий пример:
#include <iostream>
class sss
{
public:
explicit sss( int ) { std::cout << "int" << std::endl; };
sss( double ) { std::cout << "double" << std::endl; };
// Do not write such classes. It is here only for teaching purposes.
};
int main()
{
sss ddd( 7 ); // prints int
sss xxx = 7; // prints double, because constructor with int is not accessible in implicit form
return 0;
}
Display *disp = new Display();
Эта строка кода создает переменную типа Display * и инициализирует ее адресом вновь созданного объекта.
Display *disp; // (1)
disp = new Display(); // (2)
Первая строка кода просто объявляет переменную типа Display *. В зависимости от настроек вашего компилятора - указатель может быть инициализирован, а может и нет. По сути, его следует рассматривать как недопустимый указатель, который не обязательно указывает на NULL.
Вторая строка присваивает указателю адрес вновь созданного объекта.
Результат обоих фрагментов кода будет одинаковым.
При включенной оптимизации любой компилятор должен генерировать одну и ту же сборку для них обоих. С отключенной оптимизацией и с некоторой генерацией кода отладки - оба фрагмента могут генерировать совершенно другой код - во втором случае, указатель сначала будет инициализирован значением, используемым компилятором для неинициализированных указателей (что-то вроде 0xDEADBEEF или 0xEFEFEFEF - и легко узнаваемый образец). В первом сниппете - указатель всегда должен инициализироваться адресом объекта вне зависимости от настроек. Обратите внимание, что это зависит от компилятора - некоторые компиляторы могут делать то, что я говорю, некоторые могут делать что-то совершенно другое.
Вы нашли четыре способа записать одно и то же.
Примеры 1 ( Display * disp…
) и 3 ( Display * disp…
]) идентичны; расстояние вокруг *
не имеет значения. Однако стиль 1 часто предпочтительнее, потому что:
Display* disp1, disp2;
на самом деле означает:
Display *disp1, disp2;
то есть, disp2 не является указателем.
Пример 2 (разделение на две строки) имеет тот же эффект и, вероятно, будет скомпилирован в тот же код. Четвертый пример, использующий синтаксис инициализатора, также делает то же самое.
Обратите внимание, что если бы это были классы, а не указатели, могла бы быть разница в поведении и скорости.
Создается объект типа Display
и объект типа Gz Display
, это намеренно или это опечатка?
Если это опечатка, то нет никакой разницы в отношении сгенерированного кода, но первый метод предпочтительнее, поскольку нет времени, в течение которого переменная disp
находится в области видимости и не инициализируется.
1) Экземпляр GzDisplay создается во 2-м варианте, тогда как в 1-м варианте созданный экземпляр имеет тип Display (я предполагаю, что GzDisplay является подклассом Display, верно?); 2) Кроме того, что 1-й короче, во 2-м disp имеют неопределенное значение до тех пор, пока ему не будет присвоено новое значение GzDisplay (). Второй вариант дает вам шанс случайно забыть об этом и вставить код, использующий disp, перед его инициализацией.