Форум программистов, компьютерный форум CyberForum.ru

Большое количество вызовов констр-ра и дестр-ра - C++

Восстановить пароль Регистрация
 
alexsvk
8 / 8 / 1
Регистрация: 15.07.2010
Сообщений: 255
28.06.2011, 17:50     Большое количество вызовов констр-ра и дестр-ра #1
Добрый день!
Есть класс для подсчёта указателей на объект и класс, который сопровождает или поддерживает работу предыдущего, храня на него указатель.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
RefPointer.h
#pragma once
#include "StdAfx.h"
#define NDEBUG
 
template <typename T>
class RefPointer
{
public:
    RefPointer<T>(RefCount<T>* p = NULL) : ptr(p)
    { if(p) p->ref(); }
    RefPointer<T>(const RefPointer& p) { if(p.ptr) p.ptr->ref(); ptr = p.ptr; std::cout<<"refpointer()\n"; }
    ~RefPointer<T>() { release(); std::cout<<"~refpointer()\n"; }
public:
    RefPointer<T>& operator=(const RefPointer<T>& rhs)
    {
        setPointer(rhs.ptr);
        return *this;
    }
    RefPointer<T>& operator=(RefCount<T>& rhs)
    {
        setPointer(rhs);
        return *this;
    }
 
    //dereference operators
    RefCount<T>* get() const { check(); return ptr; } 
    RefCount<T>* operator->() { check(); return ptr; } 
    T& operator*() { check(); return *ptr; }
 
private:
    void setPointer(RefCount<T>* p) 
    { if(p) p->ref(); release(); ptr = p; }
    void release()
    { if(ptr && ptr->unref() == 0) delete ptr; }
 
#if defined NDEBUG
    void check() {}
#else
    void check()
    { assert(ptr != NULL || ptr->getCountForDebuggingOnly()); }
#endif
 
private:
    RefCount<T>* ptr;
};
 
template <typename T>
bool operator==(const RefPointer<T>& lhs, const RefPointer<T>& rhs ) 
{
    RefCount<T>* ltmp = lhs.get();
    RefCount<T>* rtmp = rhs.get();
    return (ltmp && rtmp) ? *ltmp == *tmp : ltmp == rtmp;
};
 
template <typename T>
bool operator!=(const RefPointer<T>& lhs, const RefPointer<T>& rhs ) 
{
    return !operator==<T>(lhs,rhs);
};
 
template <typename T>
bool operator<(const RefPointer<T>& lhs, const RefPointer<T>& rhs ) 
{
    RefCount<T>* ltmp = lhs.get();
    RefCount<T>* rtmp = rhs.get();
    return (ltmp && rtmp) ? *ltmp < *tmp : ltmp < rtmp;
};
 
template <typename T>
bool operator>(const RefPointer<T>& lhs, const RefPointer<T>& rhs ) 
{
    return !operator< <T>(lhs,rhs);
};
 
RefCount.h
#pragma once
#include "StdAfx.h"
 
template <typename Object>
class RefCount
{
    template <typename Object>
    friend class RefPointer;
public:
    RefCount<Object>(Object* p = NULL) : cpObject(p), count(0) {}
public:
    Object& operator*() const
    {
        return *cpObject;
    }
private:
    void ref() 
    {
        ++count;
    }
    unsigned unref() const
    {
        return --count;
    }
    
    unsigned getCountForDebuggingOnly() const //Only for debugging!
    { return count; }
private:
    mutable unsigned count;
    const Object* cpObject;
};
 
//main
#include "StdAfx.h"
 
template <typename T>
void foo(RefPointer<T>* p)
{
    std::vector<RefPointer<T> > v(3);
    for(int i = 0; i < 3; ++i)
        v.push_back(RefPointer<T>(*p));
    v.push_back(*p);
    //std::cout<<(*p)<<' ';
}
 
int main()
{
    RefPointer<int> ptr(new RefCount<int>(new int(5)));
    foo<int>(&ptr);
    std::cout<<"foo worked!\n";
    return 0;
}
На выходе:

refpointer()
~refpointer()
refpointer()
~refpointer()
refpointer()
~refpointer()
refpointer()
refpointer()
refpointer()
refpointer()
~refpointer()
~refpointer()
~refpointer()
refpointer()
~refpointer()
refpointer()
refpointer()
refpointer()
refpointer()
refpointer()
~refpointer()
~refpointer()
~refpointer()
~refpointer()
refpointer()
~refpointer()
refpointer()
refpointer()
~refpointer()
refpointer()
refpointer()
refpointer()
refpointer()
refpointer()
refpointer()
~refpointer()
~refpointer()
~refpointer()
~refpointer()
~refpointer()
~refpointer()
refpointer()
~refpointer()
~refpointer()
~refpointer()
~refpointer()
~refpointer()
~refpointer()
~refpointer()
foo worked!
~refpointer()
Для продолжения нажмите любую клавишу . . .


Первые 13 строк понятны, но что происходит после этого? Что является причиной стольких вызовов конструкторов и деструкторов?
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
28.06.2011, 18:09     Большое количество вызовов констр-ра и дестр-ра #2
C++
1
2
3
4
5
6
7
8
9
10
template <typename T>
void foo(RefPointer<T>* p)
{
        std::vector<RefPointer<T> > v;
        v.reserve(4);
        for(int i = 0; i < 3; ++i)
                v.push_back(RefPointer<T>(*p));
        v.push_back(*p);
        //std::cout<<(*p)<<' ';
}
alexsvk
8 / 8 / 1
Регистрация: 15.07.2010
Сообщений: 255
28.06.2011, 18:37  [ТС]     Большое количество вызовов констр-ра и дестр-ра #3
При работе push_back() конструируется временный объект, выходит так.
И ещё одно, при добавлении нового элемента в вектор размер и объём(если размер равен или больше объёму) растут, так почему же без резервации так много вызовов было?
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
28.06.2011, 18:43     Большое количество вызовов констр-ра и дестр-ра #4
а ну да кстати тут тоже ошибка скорее всего
C++
1
2
3
4
5
6
7
8
9
10
template <typename T>
void foo(RefPointer<T>* p)
{
        std::vector<RefPointer<T> > v;
        v.reserve(4);
        for(int i = 0; i < 3; ++i)
                v.push_back(p[i]);
        v.push_back(*p);
        //std::cout<<(*p)<<' ';
}
Добавлено через 1 минуту
если размер вектора достигает ёмкости он переносит свою бренную тушку на новое место, отсюда лишние вызовы
alexsvk
8 / 8 / 1
Регистрация: 15.07.2010
Сообщений: 255
28.06.2011, 19:52  [ТС]     Большое количество вызовов констр-ра и дестр-ра #5
Цитата Сообщение от pito211 Посмотреть сообщение
v.push_back(p[i]);
оператор индексации массива не определён для RefPointer. Было правильно - v.push_back(*p);
И ещё одно, кто он переносит тушку свою бренную? Если вектор, то это значит, что заново всю память под объекты распределяет?
Nick Alte
Эксперт С++
1591 / 983 / 116
Регистрация: 27.09.2009
Сообщений: 1,898
Завершенные тесты: 1
28.06.2011, 22:00     Большое количество вызовов констр-ра и дестр-ра #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от alexsvk Посмотреть сообщение
И ещё одно, при добавлении нового элемента в вектор размер и объём(если размер равен или больше объёму) растут, так почему же без резервации так много вызовов было?
Дело в том, что вектор гарантирует, что все его элементы лежат в едином кусочке памяти, последовательно. Таким образом, когда он растёт, он просто выделяет новый кусочек, побольше (скажем, в реализации MSVC в полтора раза больше старого), копирует туда значения из старого кусочка (вот тебе и вызовы конструкторов), и уничтожает старый кусочек, предварительно вызывая деструкторы хранящихся там элементов.
alexsvk
8 / 8 / 1
Регистрация: 15.07.2010
Сообщений: 255
28.06.2011, 22:46  [ТС]     Большое количество вызовов констр-ра и дестр-ра #7
Nick Alte, да, но если взглянуть на первоначальный результат работы в этой теме, то уж слишком много вызовов для 4 элементов.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.06.2011, 06:39     Большое количество вызовов констр-ра и дестр-ра
Еще ссылки по теме:

C++ Нужно заменить большое количество циклов for
Вычислите, используя рекурсию, выражение y=x+2*x^2+3*x^4+ ... для некоторого n (n – количество рекурсивных вызовов) C++
Избегая глобальных переменных напишите функцию, которая будет возвращать количество своих вызовов C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
29.06.2011, 06:39     Большое количество вызовов констр-ра и дестр-ра #8
сначала ты положил три пустых, потом ещё три одинаковых, потом ещё один, итого 7 элементов

Добавлено через 7 минут
Цитата Сообщение от alexsvk Посмотреть сообщение
оператор индексации массива не определён для RefPointer. Было правильно - v.push_back(*p);
причём здесь оператор индексации для RefPointer? я применил оператор к указателю для индексации к элементам массива
Yandex
Объявления
29.06.2011, 06:39     Большое количество вызовов констр-ра и дестр-ра
Ответ Создать тему
Опции темы

Текущее время: 16:53. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru