Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Закрытая тема
Ваша тема закрыта, почему это могло произойти? Возможно,
Нет наработок или кода, если нужно готовое решение - создайте тему в разделе Фриланс и оплатите работу.
Название темы включает слова - "Помогите", "Нужна помощь", "Срочно", "Пожалуйста".
Название темы слишком короткое или не отражает сути вашего вопроса.
Тема исчерпала себя, помните, один вопрос - одна тема
Прочитайте правила и заново правильно создайте тему.
 
Опции темы Поиск в этой теме
Старый 29.02.2016, 16:12   #1
RAFA91
Заблокирован
 
Регистрация: 06.02.2011
Сообщений: 1,999
По умолчанию Итератор списка

Добрый день !

Заметил такую опасную ситуацию

при выполнении
Код:
l.splice(it_l,temp,it_temp);
а потом it_temp++

it_temp уже указывает на элемент списка l а не temp
RAFA91 вне форума
Старый 29.02.2016, 16:23   #2
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

И в чем опасность? Что вы хотели?
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума
Старый 29.02.2016, 16:24   #3
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

полный пример можно и какой компилятор.
ибо не должно быть такого, итератор передается поидее по значению, а не ссылке.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Последний раз редактировалось Пепел Феникса; 29.02.2016 в 16:26.
Пепел Феникса вне форума
Старый 29.02.2016, 17:02   #4
RAFA91
Заблокирован
 
Регистрация: 06.02.2011
Сообщений: 1,999
По умолчанию

компилятор вижуал 10.

Вообще хотел создать функцию которая перемешивает список.

Колода карт к примеру. Для простоты эксперимента список взял типа инт.

Перемешиваю таким образом.

Делю список на 2 части. Границы раздела определяю с помощью rand();

(функция
Код:
rand_2(const int &size, int &x);
)

далее создаю 2 списка на основании границ раздела полученных от rand_2

и смешиваю как на рисунке.

___________________________

в цикле получил косяк

Код:
while (it_l != l.end())
	{
		if (it_temp != temp.end())
		{
                       l.splice(it_l,temp,it_temp);
			it_temp++;   //  уже не в списке temp !!!!!!!!!!!!!!!!!!!!!!
			it++;
                 }
		else break;
	}
___________________________________ _

полный код. малость цикл изменил.

запоминаю следующий элемент списка temp за итератором it_temp

а потом после выполнения
Код:
l.splice(it_l,temp,it_temp);
кидаю его в it_temp.

но мне кажется что есть что-то проще.

___________________________________

Код:
#include "stdafx.h"
#include <iostream>
#include <list>
#include <algorithm>

using namespace std;

template <class T>
void Show(list<T> &l)
{
	list<T> :: iterator it;
	it = l.begin();
	while (it != l.end())
	{
		cout<<*it<<" ";
		it++;
	}
	cout<<endl;
}

bool rand_2(const int &size, int &x)
{
	if (size < 2) return false;
	while (1)	
	{	
		x = rand();
		if (x > 0 && x < size) break;
	}
	return true;
}


void mix(list<int> &l, const int &x)
{
	list<int> temp;
	list<int> :: iterator it_l,it_temp,it;
	it_l = l.begin();
	advance(it_l,x);
	temp.splice(temp.begin(),l,it_l,l.end());
	//********************************************
	it_l = l.begin();
	it_temp = temp.begin();
	while (it_l != l.end())
	{
		if (it_temp != temp.end()) 
		{
			it = it_temp;
			it++;
			l.splice(it_l,temp,it_temp);
			it_l++;
			it_temp = it;
		}
		else break;
	}
	if (it_l == l.end() && it_temp != temp.end()) l.splice(it_l,temp,it_temp,temp.end());
}

int _tmain(int argc, _TCHAR* argv[])
{
	cout<<"Hello"<<endl;
	list<int> l,temp;
	list<int> :: iterator it;
	for (int i=0;i<36;i++) l.push_back(i);
	Show(l);
	//*******************************************************
	int x = 0;
	for (int i=0;i<5;i++)
	{
		if (rand_2(l.size(),x)) mix(l,x);
		Show(l);
		cout<<"*****************************"<<endl;
	}
	
	system("pause");
	return 0;
}
Изображения
Тип файла: jpg Безымянный.JPG (28.1 Кб, 67 просмотров)
RAFA91 вне форума
Старый 01.03.2016, 13:17   #5
RAFA91
Заблокирован
 
Регистрация: 06.02.2011
Сообщений: 1,999
По умолчанию

ну так что это логично что

после выполнения
Код:
l.splice(it_l,temp,it_temp);
(вставляю элемент из списка temp на который указывает итератор it_temp, в список l, перед элементом на который указывает итератор it_l)

далее делаю it_temp++

it_temp уже указывает на элемент списка l а не temp

(* it_temp) это уже элемент из списка l а не temp
RAFA91 вне форума
Старый 01.03.2016, 15:02   #6
ProBeginner
Форумчанин
 
Регистрация: 22.02.2016
Сообщений: 145
По умолчанию Программирование С/С++

Мне кажется, с итератором ничего не должно происходить при изменении контейнера, он просто должен считаться недействительным.

В вашем случае, может быть список разрезали, но элементы никуда не перемещались.

Не знаю как работает STL (для меня это тёмный лес), но логично предположить, что управление контейнером с атрибутами должно быть отделено от памяти с данными. Т.е. при разделении контейнера на части, данные не перемещаются. В результате, логическая ошибка технически не проявляется.
Возьму в кредит мильён по 100% годовых на сто лет.

Последний раз редактировалось ProBeginner; 01.03.2016 в 15:09.
ProBeginner вне форума
Старый 01.03.2016, 16:33   #7
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Пепел Феникса, итератор не изменяется,
но при splice элемент, на который он "указывает"
помещается в другой контейнер,
соответственно и итератор теперь будет на элемент другого контейнера.
Это законное поведение.

Цитата:
23.3.5.5.
...
Код:
void splice(const_iterator position, list& x, const_iterator i);
void splice(const_iterator position, list&& x, const_iterator i);
7.
Effects: Inserts an element pointed to by i from list x before position and removes the element from x. The result is unchanged if position == i or position == ++i. Pointers and references to *i continue to refer to this same element but as a member of *this. Iterators to *i (including i itself) continue to refer to the same element, but now behave as iterators into *this, not into x.
Requires: i is a valid dereferenceable iterator of x.


P.S. Зато Либерти, зато за 21 день...

Последний раз редактировалось Croessmah; 01.03.2016 в 16:40.
Croessmah вне форума
Старый 01.03.2016, 16:45   #8
ProBeginner
Форумчанин
 
Регистрация: 22.02.2016
Сообщений: 145
По умолчанию Программирование С++

Цитата:
Сообщение от Croessmah Посмотреть сообщение
и итератор теперь будет на элемент другого контейнера
Итератор не имеет обратной связи с контейнером. Когда контейнер изменяется, итератор становится недействительным. Страуструп предлагает считать итератор ссылкой, а ссылка не может контролировать структуру содержащую элемент на который она ссылается.
Наоборот, контейнер может управлять итератором, но это делается только методами контейнера явно применёнными к итератору. Сам контейнер не контролирует значения итераторов, он их просто не помнит. По этому, когда меняете структуру контейнера, все итераторы должны считаться недействительными.
Возьму в кредит мильён по 100% годовых на сто лет.
ProBeginner вне форума
Старый 01.03.2016, 16:54   #9
ProBeginner
Форумчанин
 
Регистрация: 22.02.2016
Сообщений: 145
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
итератор передается поидее по значению, а не ссылке.
Значением итератора является структура подобная ссылке. Я думаю, Вы перепутали вопрос передачи/возврата параметров в функцию и суть ссылок.
Возьму в кредит мильён по 100% годовых на сто лет.
ProBeginner вне форума
Старый 01.03.2016, 17:00   #10
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
Итератор не имеет обратной связи с контейнером. Когда контейнер изменяется, итератор становится недействительным.
Читаем внимательнее цитату из стандарта.
Плюс ко всему это list,
у него вообще надо постараться чтобы итераторы инвалидировались.
Цитата:
По этому, когда меняете структуру контейнера, все итераторы должны считаться недействительными.
Нет, не должны. Это же не vector
Цитата:
Не знаю как работает STL (для меня это тёмный лес)
собственно тогда, думаю, не стоит продолжать спор.
Croessmah вне форума
Закрытая тема


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Итератор для двусвязного списка Black_Dynamite Помощь студентам 0 07.11.2013 22:04
итератор set c++ Arrioh Помощь студентам 1 25.12.2012 16:01
Итератор списка по значению Link0 Общие вопросы по Java, Java SE, Kotlin 0 21.11.2010 14:02