Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Помогите не понимаю / 25 сообщений из 43, страница 1 из 2
26.04.2018, 22:32
    #39637044
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
Код: plaintext
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.
#include <cstdio>
#include <string>
#include <iostream>
#include <vector>

class t {
public:

    t() {
        std::cout << "run constructor" << std::endl;
    }

    t(const t &v) {
        std::cout << "run copy constructor" << std::endl;
    }

    int s = 1;
};


std::vector<t *> getVector() {
    std::vector<t *> s{};
    t tt{};
    t tt1{};
    s.emplace_back(&tt);
    s.emplace_back(&tt1);
    return s;
}

int main() {
    std::vector<t *> aVector = getVector();

    for (t *tt: aVector) {
        printf("%d", tt->s);
    }
}



Уважаемые эксперты,

подскажите почему такой код выводит 10

Хотя должен выводить 11.
...
Рейтинг: 0 / 0
26.04.2018, 22:34
    #39637045
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
И еще вопрос

t tt{};
t tt1{};


Эти два объекта были созданы на стеке

Как только мы вышли из метода - к чему мы вообще обращаемся итерируясь по вектору ?
...
Рейтинг: 0 / 0
26.04.2018, 22:35
    #39637046
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
Все я понял причину проблемы

Вопрос снят

Замена на

t *tt = new t();
t *tt1 = new t();
s.emplace_back(tt);
s.emplace_back(tt1);


решила проблему
...
Рейтинг: 0 / 0
26.04.2018, 23:32
    #39637054
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
Еще вопрос

std::vector<t> getVector() {
std::vector<t> s{};
t *tt = new t();
t *tt1 = new t();
s.push_back(*tt);
s.push_back(*tt1); -- почему на этой точке возникает вызов деструктора класса t ?
return s;
}
...
Рейтинг: 0 / 0
26.04.2018, 23:51
    #39637059
a guest
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
semen.s.semenЕще вопрос

std::vector<t> getVector() {
std::vector<t> s{};
t *tt = new t();
t *tt1 = new t();
s.push_back(*tt);
s.push_back(*tt1); -- почему на этой точке возникает вызов деструктора класса t ?
return s;
}Потому что вектор расширяется.
...
Рейтинг: 0 / 0
27.04.2018, 00:16
    #39637063
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
semen.s.semenИ еще вопрос

t tt{};
t tt1{};


Эти два объекта были созданы на стеке

Как только мы вышли из метода - к чему мы вообще обращаемся итерируясь по вектору ?
К мусору.

Не надо использовать указатели лишний раз, если STL и нет понимания.

Но в целом,нужно проучить понятия времени жизни объектов и точки их создания и удаления.

Иначе код будет неоптимальным из-за созданий/копирований штучных объектов. Раз этак в несколько медленнее.
...
Рейтинг: 0 / 0
27.04.2018, 00:18
    #39637064
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
semen.s.semenВсе я понял причину проблемы

Вопрос снят

Замена на

t *tt = new t();
t *tt1 = new t();
s.emplace_back(tt);
s.emplace_back(tt1);


решила проблемуЗато добавила утечку памяти
...
Рейтинг: 0 / 0
27.04.2018, 05:19
    #39637087
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
semen.s.semen
Код: plaintext
1.
2.
3.
4.
    t *tt = new t();
    t *tt1 = new t();
    s.emplace_back(tt);
    s.emplace_back(tt1);


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

Код: plaintext
1.
2.
3.
    for (t *tt: aVector) {
        delete tt;
    }



если не хочется удалять память вручную (лучше никогда этого вручную не делать) надо везде t* заменить на shared_ptr<t>, а tt = new t(); заменить на tt = make_shared<t>();
...
Рейтинг: 0 / 0
27.04.2018, 08:43
    #39637123
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
semen.s.semen
Код: plaintext
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.
#include <cstdio>
#include <string>
#include <iostream>
#include <vector>

class t {
public:

    t() {
        std::cout << "run constructor" << std::endl;
    }

    t(const t &v) {
        std::cout << "run copy constructor" << std::endl;
    }

    int s = 1;
};


std::vector<t *> getVector() {
    std::vector<t *> s{};
    t tt{};
    t tt1{};
    s.emplace_back(&tt);
    s.emplace_back(&tt1);
    return s;
}

int main() {
    std::vector<t *> aVector = getVector();

    for (t *tt: aVector) {
        printf("%d", tt->s);
    }
}



Уважаемые эксперты,

подскажите почему такой код выводит 10

Хотя должен выводить 11.


вообще то код ничего не должен, может выводить все, что угодно.
...
Рейтинг: 0 / 0
27.04.2018, 08:44
    #39637124
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
semen.s.semenИ еще вопрос

t tt{};
t tt1{};


Эти два объекта были созданы на стеке

Как только мы вышли из метода - к чему мы вообще обращаемся итерируясь по вектору ?

вот именно, что ни к чему. к мусору.
к тени отца Гамлета.
...
Рейтинг: 0 / 0
27.04.2018, 08:47
    #39637130
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
semen.s.semenЕще вопрос

std::vector<t> getVector() {
std::vector<t> s{};
t *tt = new t();
t *tt1 = new t();
s.push_back(*tt);
s.push_back(*tt1); -- почему на этой точке возникает вызов деструктора класса t ?
return s;
}


не возникает.

код тоже неправильный, если что.
...
Рейтинг: 0 / 0
27.04.2018, 09:57
    #39637164
a guest
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
MasterZivsemen.s.semenЕще вопрос

std::vector<t> getVector() {
std::vector<t> s{};
t *tt = new t();
t *tt1 = new t();
s.push_back(*tt);
s.push_back(*tt1); -- почему на этой точке возникает вызов деструктора класса t ?
return s;
}


не возникает.
Как кацегорично https://wandbox.org/permlink/DXb0QP66YmWi8NNp
...
Рейтинг: 0 / 0
27.04.2018, 10:08
    #39637168
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
a guestMasterZivпропущено...



не возникает.
Как кацегорично https://wandbox.org/permlink/DXb0QP66YmWi8NNp
Там на 5 объектов 3 вызова диструктора.
...
Рейтинг: 0 / 0
27.04.2018, 11:07
    #39637228
AmKad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
Для понимания того, о чем говорит a guest, поставьте
Код: plaintext
1.
s.reserve(2);

перед первым push_back.
...
Рейтинг: 0 / 0
27.04.2018, 11:09
    #39637231
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
Dima Ta guestпропущено...

Как кацегорично https://wandbox.org/permlink/DXb0QP66YmWi8NNp
Там на 5 объектов 3 вызова диструктора.
и будет их все больше и больше по мере роста вектора.
Как правильно ответил a guest происходит реаллокация вектора.
использование reserve избавит от "лишних" обьектов

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
std::vector<t> getVector() {
std::vector<t> s{};
s.reserve(2);
t *tt = new t();
t *tt1 = new t();
s.push_back(*tt);
s.push_back(*tt1); -- на этой точке НЕ возникает вызов деструктора класса t 
return s;
}
...
Рейтинг: 0 / 0
28.04.2018, 09:19
    #39637859
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
OoCcи будет их все больше и больше по мере роста вектора.
Как правильно ответил a guest происходит реаллокация вектора.
использование reserve избавит от "лишних" обьектов

Или можно сделать noexcept move-конструктор. Именно такой будет вызываться при реаллокации вектора, если существует, взамен конструктору копирования.
...
Рейтинг: 0 / 0
28.04.2018, 16:37
    #39638116
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
NekZOoCcи будет их все больше и больше по мере роста вектора.
Как правильно ответил a guest происходит реаллокация вектора.
использование reserve избавит от "лишних" обьектов

Или можно сделать noexcept move-конструктор. Именно такой будет вызываться при реаллокации вектора, если существует, взамен конструктору копирования.
Нет. Это нехорошо. В большинстве случаев замена конструктора копирования на конструктор перемещения большой выгоды не даёт. Реаллокэйшн нужно исключать. Иначе этот контэйнер работает в а-ля-джава режиме.
...
Рейтинг: 0 / 0
28.04.2018, 17:24
    #39638133
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
OoCcНет. Это нехорошо. В большинстве случаев замена конструктора копирования на конструктор перемещения большой выгоды не даёт . Реаллокэйшн нужно исключать. Иначе этот контэйнер работает в а-ля-джава режиме.

Лолшлто? Про замену одного конструктора другим никто не говорил.
Именно move-семантика позволяет избежать копирования при вынужденном реаллокейшне. Разумеется, когда ты знаешь приблизительное или точное количество элементов нужно использовать reserve. Но, вектор так спроектирован чтобы расширяться, вынуждено перемещая объекты в новую область памяти, когда упирается в размер выделенного блока. Так что, когда есть возможность организовать move-конструктор и оператор присваивания для элементов в векторе -- лучше всего воспользоваться этой возможностью.
...
Рейтинг: 0 / 0
28.04.2018, 18:56
    #39638174
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
NekZИменно move-семантика позволяет избежать копирования при вынужденном реаллокейшне.
Можно поподробнее. Не силен в современном С++.

В С++ нет реаллокейшена, т.е. realloc() не используется. Увеличение размера вектора это как минимум memcpy(), если при этом пресечь вызовы деструкторов и конструкторов, то можно на этом время сэкономить.
...
Рейтинг: 0 / 0
28.04.2018, 18:59
    #39638178
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
Похоже, чуваку нужен простой контейнер с указателями. Думаю, нужным ему ответом будет unique_ptr:

Код: plaintext
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.
class CSome
{
	static int nInstanceCounter;
public:
	CSome(const int _n) : nField(_n), nInstanceNumber(++nInstanceCounter)
	{
		wcout << L"CSome ctor { nField = " << nField << ", nInstanceNumber = " << nInstanceNumber << "}" << endl;
	}
	CSome(const CSome& some) : nField(some.nField), nInstanceNumber(++nInstanceCounter)
	{
		nField = some.nField;
		wcout << L"CSome copy ctor { nField = " << nField << ", nInstanceNumber = " << nInstanceNumber << "}" << endl;
	}
	~CSome()
	{
		wcout << L"CSome dtor { nField = " << nField << ", nInstanceNumber = " << nInstanceNumber << "}" << endl;
	}
	int nField;
	int nInstanceNumber;
private:
	CSome() {}
};

int CSome::nInstanceCounter = 0;

int main()
{

	vector< unique_ptr<CSome> > vs;
	vs.push_back(make_unique<CSome>(5));
	vs.push_back(make_unique<CSome>(6));

	getchar();
	return 0;
}
...
Рейтинг: 0 / 0
28.04.2018, 19:06
    #39638184
13th
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
semen.s.semen, если ты не в курсе, то в скобках для unique_ptr<CSome> указываются параметры как для конструктора SCome, т.е. если у тебя конструктор выглядит CSome(5), то и указатель надо создавать как make_unique<CSome>(5).
...
Рейтинг: 0 / 0
28.04.2018, 20:51
    #39638210
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
Dima TМожно поподробнее. Не силен в современном С++.
В С++ нет реаллокейшена, т.е. realloc() не используется.

Реаллокейшн не значил вызов realloc'а. Это просто удобный термин обозначающий определённую последовательность действий в реализации std::vector'а. Например, в док референсе употребляется термин "Reallocation". Не суть, в общем.
Dima TУвеличение размера вектора это как минимум memcpy(), если при этом пресечь вызовы деструкторов и конструкторов, то можно на этом время сэкономить.
memcpy смотря для чего. Для POD-типов memcpy -- вполне себе решение.
А вот для комплексных типов классов и структур не всё так просто. Хотя бы потому что у объекта в векторе тогда вообще не будет возможности хоть как-то уведомить внешний мир, что он-то оказывается переехал по новому адресу. Ну или хотя бы потому что внутри объекта могут быть сохранены указатели на внутренние поля (why not?), что сделает их невалидными после копирования в новое место. Вообще, ЕМНИП нет никаких гарантий, что memcpy'ed объект будет работать валидно, ибо это Implementation Defined. Поэтому по классике старых плюсов, вызываются copy-ctor'ы на только что выделенном куске памяти через placement new и затем деструкторы. Понятно, что по задумке конструктор копирования создаёт копию объекта, в то время как move-ctor просто меняет владение внутренними ресурсами объекта. Советую глянуть это короткое видео от Джейсона Тёрнера, который на наглядном примере объясняет как это работает.

YouTube Video
...
Рейтинг: 0 / 0
28.04.2018, 23:39
    #39638221
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
NekZOoCcНет. Это нехорошо. В большинстве случаев замена конструктора копирования на конструктор перемещения большой выгоды не даёт . Реаллокэйшн нужно исключать. Иначе этот контэйнер работает в а-ля-джава режиме.

Лолшлто? Про замену одного конструктора другим никто не говорил.
Именно move-семантика позволяет избежать копирования при вынужденном реаллокейшне. Разумеется, когда ты знаешь приблизительное или точное количество элементов нужно использовать reserve. Но, вектор так спроектирован чтобы расширяться, вынуждено перемещая объекты в новую область памяти, когда упирается в размер выделенного блока. Так что, когда есть возможность организовать move-конструктор и оператор присваивания для элементов в векторе -- лучше всего воспользоваться этой возможностью.
Лолто. А move семантика это что за зверь? Это и есть замена конструкторов копирования на конструкторы перемещения при реаллокации вектора. Дальше читаем снова моё предыдущее сообщение.
...
Рейтинг: 0 / 0
29.04.2018, 00:12
    #39638225
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
NekZНо, вектор так спроектирован чтобы расширяться, вынуждено перемещая объекты в новую область памяти, когда упирается в размер выделенного блока. Так что, когда есть возможность организовать move-конструктор и оператор присваивания для элементов в векторе -- лучше всего воспользоваться этой возможностью.
Глупости. в 99% случаях замена вектора на декъю решает все проблемы с внутренними перемещениями и лишними обьектами.
...
Рейтинг: 0 / 0
29.04.2018, 08:37
    #39638248
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите не понимаю
OoCcА move семантика это что за зверь?

RTFM

OoCcЭто и есть замена конструкторов копирования на конструкторы перемещения при реаллокации вектора. Дальше читаем снова моё предыдущее сообщение.
Да нету никакой замены. Конструкторы копирования и перемещения могут сосуществовать в одном классе легко. Вектор при реаллокации смотрит через type_traits есть ли у T noexcept move-конструктор и использует его. Если его нет, он будет использовать copy-конструктор. Если и его нет, попытается найти обычный move-констуктор. Если его нет, то ничего не скомпилируется. Читаем сначала раздел Exceptions/(since C++11) . Дальше подкрепляем матчасть видео из моего предыдущего сообщения.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Помогите не понимаю / 25 сообщений из 43, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]