Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вызов конструктора

309
23 сентября 2006 года
el scorpio
1.1K / / 19.09.2006
Есть вопрос по вызову конструктора для инициализации выделенной области памяти.

Во время разработки класса, аналогичного DynamicArray (целесообразность этого прошу не обсуждать - просто НАДО), встала проблема изменения кол-ва объектов в массива

 
Код:
void TArray::SetCount (int NewCount)
{[INDENT] if (NewCount == Count) return;
if (NewCount < 0) throw Exception ("");
for (int i = _fCount-1; i >= NewCount; i--)
     (_fItems+i)->~TItem(); //Вызов деструктора для элемента массива
_fItems = (TItem*) realloc (_fItems, sizeof(TItem)*NewCount); // Изменение размера выделенной памяти
for (int i = _fCount; i < NewCount; i++)
     (_fItems+i)->TItem(); //Вызов конструктора для инициализации элемента массива
_fCount = NewCount
[/INDENT]}

В строке вызова конструктора возникает ошибка компиляции :confused:
Пришлось изменить эту строку так, как написано в DynamicArray.
 
Код:
new (_fItems+i) TItem();

С этим всё понятно - создание объекта по указанному адресу

А почему всё-таки нельзя прямо вызвать конструктор?
5.4K
06 октября 2006 года
Svyatozar
221 / / 11.09.2006
[QUOTE=el scorpio]А почему всё-таки нельзя прямо вызвать конструктор?[/QUOTE]
Потому что вызов конструктора напрямую в С++ означает создание временного объекта:

Fraction fr = Fraction(1, 2) + Fraction(3, 5);

Создаются два временных объекта: дроби 1/2 и 3/5, сумма которых помещается в третий временный объект, затем вызывается перегруженный оператор = который должен скопировать содержимое временного объекта в создаваемый объект fr.
3
06 октября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=el scorpio]
А почему всё-таки нельзя прямо вызвать конструктор?[/QUOTE]
Конструктор напрямую вызвать можно.
В твоем случае компилятор ругается потому, что он не может разобрать конструкцию (_fItems+i)->TItem(), т.к. конструктор - метод с именем совпадающим с названием типа.
По мнению компилятора после -> должно идти имя члена, но не тип, а TItem - это в первую очередь тип.
Аналогично не получится вызвать оператор преобразования типа, например operator int().

В таких случаях надо явно указывать, что это метод/оператор, а не название типа:
(_fItems+i)->TItem::TItem();
(_fItems+i)->operator int();
3
06 октября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=Svyatozar]Потому что вызов конструктора напрямую в С++ означает создание временного объекта:
[/QUOTE]
Вызов конструктора не обозначает создание объекта. За создание отвечает оператор new, конструктор же инициализирует объект.

[QUOTE=Svyatozar]
Fraction fr = Fraction(1, 2) + Fraction(3, 5);

Создаются два временных объекта: дроби 1/2 и 3/5, сумма которых помещается в третий временный объект, затем вызывается перегруженный оператор = который должен скопировать содержимое временного объекта в создаваемый объект fr.
[/QUOTE]
Не совсем так. В данном примере будут вызваны:
1) Fraction::Fraction(3, 5)
2) Fraction::Fraction(1, 2)
3) Fraction::operator+
4) Fraction::Fraction( 1/2 + 3/5 )

Ни оператор =, ни конструктор копирования вызваны не будут.
309
06 октября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Green]Вызов конструктора не обозначает создание объекта. За создание отвечает оператор new, конструктор же инициализирует объект.
[/QUOTE]
Пардон за неточность терминологии - именно инициализацию объекта по указанному адресу я и имел в виду.

Хотел было сказать "спасибо", но вот только код компилироваться не хочет :(
 
Код:
AnsiString *pStr = (AnsiString*) malloc (sizeof (AnsiString));
pStr->AnsiString::AnsiString(); // 'AnsiString' is not a member of 'AnsiString'
*pStr = Application->Title;
pStr->~AnsiString(); // Вызов деструктора - ошибок не наблюдается
free (pStr);
3
06 октября 2006 года
Green
4.8K / / 20.01.2000
У меня нетникакой инф. о классе AnsiString, поэтому я попробовал такой вариант:
Код:
#include <malloc.h>
#include <iostream>
using namespace std;


class AnsiString
{
public:
    AnsiString() {
        cout << "AnsiString()" << endl;
    }

    ~AnsiString() {
        cout << "~AnsiString()" << endl;
    }
};


int main()
{
    AnsiString *pStr = (AnsiString*) malloc (sizeof (AnsiString));
    pStr->AnsiString::AnsiString();
    pStr->~AnsiString();
    free (pStr);

    return 0;
}

у меня компилируется (MSVC 2005).

Кстати, говоря, что конструктор МОЖНО вызвать напрямую, я не делал призыв к действию. Этим лучше не злоупотреблять. :)
5.4K
06 октября 2006 года
Svyatozar
221 / / 11.09.2006
[QUOTE=Green]Вызов конструктора не обозначает создание объекта. За создание отвечает оператор new, конструктор же инициализирует объект.[/QUOTE]
Объект можно создать и без оператора new:
Myclass myobject(3, 4);
В данном случае место под объект выделяется без оператора new, и вызывается конструктор.
[QUOTE=Green]Не совсем так. В данном примере будут вызваны:
1) Fraction::Fraction(3, 5)
2) Fraction::Fraction(1, 2)
3) Fraction::operator+
4) Fraction::Fraction( 1/2 + 3/5 )

Ни оператор =, ни конструктор копирования вызваны не будут.[/QUOTE]
согласен что оператор = здесь не будет вызван, хотя он и присутствует. Исправляю свою ошибку. Но с остальным не согласен:

 
Код:
Fraction fr;
    fr = Fraction(1, 2) + Fraction(3, 5);

Я настаиваю на том что и в исправленном и в неисправленном моем примере создаются временные объекты, например a и b:
 
Код:
Fraction fr;
    {
        Fraction b(3, 5);
        Fraction a(1, 2);
        fr = a.operator+(b);
    }

Что касается прямого вызова конструктора через указатель объекта:
pStr->AnsiString::AnsiString();
gcc такого безобразия не пропустит: "error: invalid use of 'class AnsiString'"
1.9K
06 октября 2006 года
[*]Frosty
278 / / 17.06.2006
[QUOTE=Green]
Не совсем так. В данном примере будут вызваны:
1) Fraction::Fraction(3, 5)
2) Fraction::Fraction(1, 2)
3) Fraction::operator+
4) Fraction::Fraction( 1/2 + 3/5 )

Ни оператор =, ни конструктор копирования вызваны не будут.[/QUOTE]
А почему оператор-то = не будет вызываться?
По-моему так будет:
1) Создаеться вр. объект и вызываеться Fraction::Fraction(3, 5)
2) Создаеться вр. объект и вызываеться Fraction::Fraction(1, 2)
3) Создаеться вр. объект и вызываеться Fraction::operator+
4) вызываеться Fraction::operator=
3
06 октября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=Svyatozar]Объект можно создать и без оператора new:
Myclass myobject(3, 4);
В данном случае место под объект выделяется без оператора new, и вызывается конструктор.
[/QUOTE]
Создание объекта - это выделение памяти + вызов конструктора.
Память может быть выделена как в куче (new), так и на стеке.
Я же говорил совсем о другом: вызов конструктора - это ещё не создание объекта в противовес твоим словам "Потому что вызов конструктора напрямую в С++ означает создание временного объекта:"

[QUOTE=Svyatozar]
согласен что оператор = здесь не будет вызван, хотя он и присутствует. Исправляю свою ошибку. Но с остальным не согласен:

 
Код:
Fraction fr;
    fr = Fraction(1, 2) + Fraction(3, 5);

Я настаиваю на том что и в исправленном и в неисправленном моем примере создаются временные объекты, например a и b:
[/QUOTE]
А кто с этим спорит?
Да, создаются два временных объекта на стеке.
Я перечислил вызовы, которые будут осуществлены, чтобы показать, что оператор = вызван не будет.

[QUOTE=Svyatozar]
Что касается прямого вызова конструктора через указатель объекта:
pStr->AnsiString::AnsiString();
gcc такого безобразия не пропустит: "error: invalid use of 'class AnsiString'"[/QUOTE]
Ну это не безобразие, а вполне нормальная конструкция, например, когда надо вызвать виртуальный метод определенного класса в иерархии.
Возможно, что с конструкторами такое не прокатит, но ответ надо искать в стандарте, а не в реализации какого-либо компилятора.
3
06 октября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE='
  • Frosty']А почему оператор-то = не будет вызываться?
    По-моему так будет:
    1) Создаеться вр. объект и вызываеться Fraction::Fraction(3, 5)
    2) Создаеться вр. объект и вызываеться Fraction::Fraction(1, 2)
    3) Создаеться вр. объект и вызываеться Fraction::operator+
    4) вызываеться Fraction::operator=[/QUOTE]

    1 и 2 пункты имеют место
    3-й пункт выглядит иначе: вызывается operator+ в ходе которого создается объект.
    В С++ есть некоторая оптимизация (это не оптимизация оптимизатора), а оптимизация заложенная в сам язык, что в подобных случаях результирующий объект и будет результатом всей строки.
    Домашнее задание: найдите это в стандарте, а то вдруг я ошибаюсь :)

    Но даже если бы такой оптимизации не было, то оператор = не вызвался, а вызвался бы копирующий конструктор, т.к. в C++ записи
    A a = b;
    и
    A a(b);
    тождественны.
  • 1.9K
    06 октября 2006 года
    [*]Frosty
    278 / / 17.06.2006
    Уточняю 3-й пункт:
    1) Создаеться вр. объект и вызываеться Fraction::Fraction(3, 5)
    2) Создаеться вр. объект и вызываеться Fraction::Fraction(1, 2)
    3) вызываеться Fraction Fraction:operator+(Fraction&, Fraction&)
    3.1) return object - вызывается конст. копирования!
    В стеке создаеться вр. объект путем копирования object!
    4) вызываеться Fraction:operator=(fr, вр. объект из 3.1)
    Насчет 4-го сделай ссылку. Руки дойдут почитаю сам стандарт, а пока ...
    5.4K
    06 октября 2006 года
    Svyatozar
    221 / / 11.09.2006
    el scorpio:
    если очень нужно использовать malloc(), тебе придется перегружать операторы new и delete:

    #include <stdlib.h>
    class X {
    //...
    public:
    void * operator new(size_t size) {return (malloc(size)); }
    void operator delete(void *ptr) { free(ptr); }
    X(unsigned size) { new(size); }
    ~X() { delete(this); }

    Как я уже сказал, в моем исправленном примере:
     
    Код:
    Fraction fr;
        fr = Fraction(1, 2) + Fraction(3, 5);

    operator= вызывается

    А что касается стандарта языка, то компилятор от мелкомягких не соответствует стандарту ANSI.
    3
    06 октября 2006 года
    Green
    4.8K / / 20.01.2000
    [QUOTE=Svyatozar]
    А что касается стандарта языка, то компилятор от мелкомягких не соответствует стандарту ANSI.[/QUOTE]
    А какой вообще соответствует? :D
    3
    06 октября 2006 года
    Green
    4.8K / / 20.01.2000
    [QUOTE='
  • Frosty']
    3.1) return object - вызывается конст. копирования!
    В стеке создаеться вр. объект путем копирования object!
    [/QUOTE]
    Не обязательно конструктор копирования, все зависит от реализации оператора +. Скорее всего даже, что не копирования.

    [QUOTE='
  • Frosty']
    4) вызываеться Fraction:operator=(fr, вр. объект из 3.1)
    Насчет 4-го сделай ссылку. Руки дойдут почитаю сам стандарт, а пока ...[/QUOTE]
    Смотри сюда (п.2):
    http://www.open-std.org/jtc1/sc22/open/n2356/special.html#class.copy
  • 309
    07 октября 2006 года
    el scorpio
    1.1K / / 19.09.2006
    [QUOTE=Green]У меня нет никакой инф. о классе AnsiString, поэтому я попробовал такой вариант:
    ...
    у меня компилируется (MSVC 2005).

    Кстати, говоря, что конструктор МОЖНО вызвать напрямую, я не делал призыв к действию. Этим лучше не злоупотреблять. :)[/QUOTE]
    Что значит "нет инфы" :confused:.
    Общеупотребительный тип C++ Builder'а.
    Кстати, то, что Borland C++ Builder 6.0 не компилирует такой код - это баг или стандарт?
    5.4K
    07 октября 2006 года
    Svyatozar
    221 / / 11.09.2006
    [QUOTE=Green]А какой вообще соответствует? :D[/QUOTE]
    Intel C++ compiler 9.1
    3
    07 октября 2006 года
    Green
    4.8K / / 20.01.2000
    [QUOTE=el scorpio]Что значит "нет инфы" :confused:.
    Общеупотребительный тип C++ Builder'а.
    Кстати, то, что Borland C++ Builder 6.0 не компилирует такой код - это баг или стандарт?[/QUOTE]
    Просто, у меня нет Builder'а.
    А баг это или стандарт - это интересный вопрос, в котором я уже предлагал разобраться.

    [QUOTE=Svyatozar]
    Intel C++ compiler 9.1
    [/QUOTE]
    :)
    Скажу по секрету: ни один компилятор не соответствует стандарту в полной мере.
    Доказательств можно привести множество и в каждом случае они свои.
    Но есть и общие черты несоответствия, например, export template.
    309
    07 октября 2006 года
    el scorpio
    1.1K / / 19.09.2006
    [QUOTE=Green]А баг это или стандарт - это интересный вопрос, в котором я уже предлагал разобраться.
    [/QUOTE]
    Хорошая идея, давай разберёмся. Только у меня стандартов под рукой нет :). Кстати, а что конкретно по этому поводу говорит Устав? (пардон, Стандарт :D)
    5.4K
    07 октября 2006 года
    Svyatozar
    221 / / 11.09.2006
    [QUOTE=Green]
    Скажу по секрету: ни один компилятор не соответствует стандарту в полной мере.
    Доказательств можно привести множество и в каждом случае они свои.
    Но есть и общие черты несоответствия, например, export template.[/QUOTE]
    И Слава Богу! Неслыханный маразм этот export template.

    Необходимо каждому понять что Шаблоны - это те же макросы: компилятор для каждого типа создает отдельный код следуя этому макросу. Поэтому нельзя скрыть реализацию шаблона в скомпилированной библиотеке. Поэтому никакой export template не нужен, и даже вреден так как вносит ненужную путаницу.
    3
    08 октября 2006 года
    Green
    4.8K / / 20.01.2000
    [QUOTE=Svyatozar]
    Необходимо каждому понять что Шаблоны - это те же макросы:компилятор для каждого типа создает отдельный код следуя этому макросу.
    [/QUOTE]
    Ну и что? Не вижу сходства с макросами.
    Сравнивать шаблон с макросом все равно, что счёты с компьютером.

    [QUOTE=Svyatozar]
    Поэтому нельзя скрыть реализацию шаблона в скомпилированной библиотеке. Поэтому никакой export template не нужен, и даже вреден так как вносит ненужную путаницу.[/QUOTE]
    И можно (мета-код) и порой нужно. Кстати, Comeau частично поддерживает экспорт шаблонов.

    Но изначально я говорил о другом: каждый компилятор в чем-то не соответствует стандарту.
    3
    08 октября 2006 года
    Green
    4.8K / / 20.01.2000
    [QUOTE=el scorpio]Хорошая идея, давай разберёмся. Только у меня стандартов под рукой нет :). Кстати, а что конкретно по этому поводу говорит Устав? (пардон, Стандарт :D)[/QUOTE]
    Вот стандарт 2003 года:
    http://anatolix.naumen.ru/files/books/CPPStandard2003.zip

    дерзай :)
    5.4K
    08 октября 2006 года
    Svyatozar
    221 / / 11.09.2006
    [QUOTE=Green]Ну и что? Не вижу сходства с макросами.
    Сравнивать шаблон с макросом все равно, что счёты с компьютером.[/QUOTE]а я вижу сходство.[QUOTE=Green]
    И можно (мета-код) и порой нужно. Кстати, Comeau частично поддерживает экспорт шаблонов.[/QUOTE]Говорю же: нельзя скрыть реализацию. Вот упертый! И в Comeau тоже нельзя. Он тоже требует исходники в которых описаны шаблонные функции. Нах%р нужен export если я просто include могу сделать????
    [QUOTE=Green]Но изначально я говорил о другом: каждый компилятор в чем-то не соответствует стандарту.[/QUOTE]
    Согласен, на 100% не соответствуют, но в химии никогда не бывает измеренных абсолютных 100%.

    Просто я увидел слово "стандарт" в контексте разговора о Мелкомягких, и тут я просто не мог удержаться. Даже сейчас колотит в судорогах и не отпускает: неврный тик что ли в запущенной стадии?
    3
    08 октября 2006 года
    Green
    4.8K / / 20.01.2000
    [QUOTE=Svyatozar]Говорю же: нельзя скрыть реализацию. Вот упертый! И в Comeau тоже нельзя. Он тоже требует исходники в которых описаны шаблонные функции. Нах%р нужен export если я просто include могу сделать????
    [/QUOTE]
    Так вот при наличии полноценной реализации в компиляторе export, можно скрыть и реализацию шаблонных методов.

    [QUOTE=Svyatozar]
    Просто я увидел слово "стандарт" в контексте разговора о Мелкомягких, и тут я просто не мог удержаться. Даже сейчас колотит в судорогах и не отпускает: неврный тик что ли в запущенной стадии?
    [/QUOTE]
    Да относительно нормально всё у MS с поддержкой стандарта. Во всяком случае не хуже, чем у большинства др. компиляторов.
    3.3K
    08 октября 2006 года
    ShadyMan
    191 / / 15.07.2006
    [QUOTE=Green]http://anatolix.naumen.ru/files/books/CPPStandard2003.zip[/QUOTE]
    Так вот где стандарты зарыты! Эх, жаль раньше не знал: а то бы ответил squirL'у по поводу того, что декларация переменных для блока - это только в С++! "There are four kinds of scopes: function, file, block, and function prototype" - стандарт С ещё 99 года. (Ивините, что не по теме).
    5.4K
    09 октября 2006 года
    Svyatozar
    221 / / 11.09.2006
    [QUOTE=Green]Так вот при наличии полноценной реализации в компиляторе export, можно скрыть и реализацию шаблонных методов.[/QUOTE]
    Не, ты точно не читаешь что я пишу. Так хотя бы прочти что пишет твой долбаный майкрософт: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core_Templates_vs.._Macros.asp
    Шаблоны - как макросы! И компилируются отдельно для каждого типа данных. Нельзя их заранее для всех возможных типов прекомпилировать и поместить в выполняемый файл. Так как же ты их скроешь?? При чем тут реализация?

    [QUOTE=Green]Да относительно нормально всё у MS с поддержкой стандарта. Во всяком случае не хуже, чем у большинства др. компиляторов.[/QUOTE]Ты знаком с большинством других компиляторов?
    309
    09 октября 2006 года
    el scorpio
    1.1K / / 19.09.2006
    Svyatozar и все, все, все...
    Может не надо офтоп разводить.

    Господа модераторы, пожалуйста, вынесите всё вышесказанное про "шаблоны" в отдельную тему.
    3
    09 октября 2006 года
    Green
    4.8K / / 20.01.2000
    [QUOTE=Svyatozar]Не, ты точно не читаешь что я пишу.
    [/QUOTE]
    Да нет, это ты не понимаешь, что я тебе отвечаю.

    [QUOTE=Svyatozar]
    Так хотя бы прочти что пишет твой долбаный майкрософт: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core_Templates_vs.._Macros.asp
    [/QUOTE]
    Ну во-первых, Майкрософт не мой, а жаль... :)
    Во-вторых, если ты прочел сам инф. по ссылке, то мог бы увидеть, что там написано следущее: "In many ways, templates work like preprocessor macros.... However, there are many differences between a macro like this:". Я на всякий случай переведу: "Во многих случаях шаблоны работают, как макросы... Однако, есть множество отличий от макросов, как например:"

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

    [QUOTE=Svyatozar]
    Шаблоны - как макросы! И компилируются отдельно для каждого типа данных.
    [/QUOTE]
    Да, с этим никто не спорит. Шаблоны компилируются в объектный код отдельно для каждого инстанированного типа.

    [QUOTE=Svyatozar]
    Нельзя их заранее для всех возможных типов прекомпилировать и поместить в выполняемый файл. Так как же ты их скроешь??
    [/QUOTE]
    Я уже говорил, ты невнимательно читаешь. Шаблоны могут быть предкомпилированы в мета-код, как например, предкомпилируются скрипты языка Python.

    [QUOTE=Svyatozar]
    При чем тут реализация?
    [/QUOTE]
    При том, что на должном уровне это пока не реализовано.

    [QUOTE=Svyatozar]
    Ты знаком с большинством других компиляторов?[/QUOTE]
    Я знаком со множеством распространненных компиляторов (MS, gcc в различных вариациях, Metrowerks, Comeau, Borland, Intel, и пр.), так что исходя из правила 20/80, можно сказать, что "знаком с большинством других компиляторов".

    P.S. Если хочешь поговорить о проблемах компиляторов и о шаблонах, то давай сделаем это в отдельной теме.
    1.9K
    09 октября 2006 года
    [*]Frosty
    278 / / 17.06.2006
    [QUOTE=Green]
    [QUOTE=
  • Frosty]
    3.1) return object - вызывается конст. копирования!
    В стеке создаеться вр. объект путем копирования object!
    [/QUOTE]
    Не обязательно конструктор копирования, все зависит от реализации оператора +. Скорее всего даже, что не копирования.
    [/QUOTE]
    C 4-м разабрался на вых., а что Вы насчет 3-го говорите?
  • Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
    Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог