powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Помогите не понимаю
25 сообщений из 43, страница 1 из 2
Помогите не понимаю
    #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
Помогите не понимаю
    #39637045
semen.s.semen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И еще вопрос

t tt{};
t tt1{};


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

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

Вопрос снят

Замена на

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


решила проблему
...
Рейтинг: 0 / 0
Помогите не понимаю
    #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
Помогите не понимаю
    #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
Помогите не понимаю
    #39637063
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semenИ еще вопрос

t tt{};
t tt1{};


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

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

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

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

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

Вопрос снят

Замена на

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


решила проблемуЗато добавила утечку памяти
...
Рейтинг: 0 / 0
Помогите не понимаю
    #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
Помогите не понимаю
    #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
Помогите не понимаю
    #39637124
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semenИ еще вопрос

t tt{};
t tt1{};


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

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

вот именно, что ни к чему. к мусору.
к тени отца Гамлета.
...
Рейтинг: 0 / 0
Помогите не понимаю
    #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
Помогите не понимаю
    #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
Помогите не понимаю
    #39637168
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestMasterZivпропущено...



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

перед первым push_back.
...
Рейтинг: 0 / 0
Помогите не понимаю
    #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
Помогите не понимаю
    #39637859
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OoCcи будет их все больше и больше по мере роста вектора.
Как правильно ответил a guest происходит реаллокация вектора.
использование reserve избавит от "лишних" обьектов

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

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

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

В С++ нет реаллокейшена, т.е. realloc() не используется. Увеличение размера вектора это как минимум memcpy(), если при этом пресечь вызовы деструкторов и конструкторов, то можно на этом время сэкономить.
...
Рейтинг: 0 / 0
Помогите не понимаю
    #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
Помогите не понимаю
    #39638184
13th
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
semen.s.semen, если ты не в курсе, то в скобках для unique_ptr<CSome> указываются параметры как для конструктора SCome, т.е. если у тебя конструктор выглядит CSome(5), то и указатель надо создавать как make_unique<CSome>(5).
...
Рейтинг: 0 / 0
Помогите не понимаю
    #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
Помогите не понимаю
    #39638221
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZOoCcНет. Это нехорошо. В большинстве случаев замена конструктора копирования на конструктор перемещения большой выгоды не даёт . Реаллокэйшн нужно исключать. Иначе этот контэйнер работает в а-ля-джава режиме.

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

RTFM

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


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