*** ВНИМАНИЕ: Блог переехал на другой адрес - demin.ws ***

суббота, 21 февраля 2009 г.

Разница между T() и T

Как совершенно справедливо было замечено в комментариях в посте про разницу между new T() и new T — при объявлении автоматической переменной, а не динамической через new, нельзя использовать скобки, если подразумевается вызвать конструктор по умолчанию. То есть нельзя писать:
T a();
а надо писать:
T a;
так как в первом случае такая запись будет означать декларацию функции a, которая возвращает тип T, а далеко не декларацию переменной класса T с вызовом конструктора по умолчанию.

Не спорю, это очевидно для профессионалов. Для новичков же порой подобная "неочевидная" разница вызывает затруднения, поэтому приведу простейший пример, которые расставит все на свои места.

#include <iostream>
class T {
public:
T() { std::cout << "constructor T()"; }
};

int main() {
std::cout << "T a: ";
// Это синтаксис создания экземпляра класса T с вызовом
// конструктора по умолчанию.
T a;
std::cout << std::endl;

std::cout << "T b(): ";
// А вот это декларация функции "b" без аргументов,
// которая возвращает тип T.
T b();
std::cout << std::endl;
return 0;
}
Данная программа напечатает:
T a: constructor T()
T b():
Видно, что для T b(); никакой конструктор не был вызван. Что в целом и ожидалось.

Использование круглых скобок может быть весьма тонким вопросом в С++.


Другие посты по теме:

9 комментариев:

  1. "Видно, что для T a(); никакой конструктор не был вызван. Что в целом и ожидалось."
    Скорее никакой конструктор не был вызван для T b();

    ОтветитьУдалить
  2. Хотел бы дополнить этот "темный угол" примером из книги Скотта Майерса "Эфективное использование STL".
    T A( B() ) - объявление функции, которая принимает первым параметром указатель на функцию B f(void). Другими словами - B (f*)(void).
    T A( (B()) ) - объявление переменной и вызов конструстора T::T( B ).

    ОтветитьУдалить
  3. Напоролся в своё время несколько раз))
    Неужели компилятору нормально, что функция объявляется внутри функции?

    ОтветитьУдалить
  4. sanchosz, то есть
    T A( (void) );
    сработает как объявление
    переменной с вызовом конструктора?

    ОтветитьУдалить
  5. k06a: Это декларация прототипа фукнции, чтобы ее можно было бы вызвать, например, "b();", а не тела функции как такового.

    ОтветитьУдалить
  6. Александр, ну да. Но тем не менее мне не ясно зачем может понадобиться объявлять прототип функции ВНУТРИ другой функции. Ведь логичнее объявлять прототип выше/ниже какой-нибудь из функций.

    ОтветитьУдалить
  7. Этот комментарий был удален автором.

    ОтветитьУдалить
  8. Ещё надо сказать, что если в T есть конструктор имеющий параметры например T::T(int), то конструкция T b(0); это не декларация функции как может ожидаться, а именно создание объекта b.

    ОтветитьУдалить