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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.74
Bers
Заблокирован
#1

Не хватает знаний. Не знаю, как на с++ реализовать возможность - C++

15.11.2011, 10:31. Просмотров 2512. Ответов 67
Метки нет (Все метки)

Есть одна вещь, которую у меня сделать никак не получается.

В моей старенькой 2008 студии отсутствуют стандартизированные интеллектуальные указатели.
По этой причине я когда то написал собственные велосипеды для разных типов указателей.

Вот так выглядит прототип метода, который загружает данные в сильнвй указатель (который умеет шариться)


C++
1
2
3
4
void Input(TypeT* &Object); //принять право владения объектом. 
                                //Источник - указатель,
                                // который в конце операции обнулится 
                                //(больше не будет владеть объектом)
Обратите внимание, что на входе ссылка на указатель, а не просто указатель.
Это нужно специально для того, что бы можно было обнулить аргумент.

Вот так выглядит реализация метода:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void_TSharedPointer::Input(TypeT * &pObject)
{
    if(pObject==NULL_PTR) {   Release(); return;  }
 
    //следующее условие не корректно
    //Потому что , ситуация, 
    //когда аргумент указывает туда же,
    //куда и смартпоинтер возникнуть не может
    //Но покамест закроем на это глаза
 
    if(mp_Pointer != pObject)  
    {  
        Release();  
        mp_Pointer = pObject;
        mp_CounterLink=new int(1);
        pObject=NULL_PTR; 
    }
}
Обнуление аргумента гарантирует интеллектуальному указателю, что он действительно будит являться единственным владельцем объекта. И вызывающая сторона не сможет больше никак в обход его ничего сделать с ввереным ему объектом.

Все это здорово, и прекрасно.

Вот так это работает на практике:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
 
    int* ptr= new int;
 
    TSharedPointer<int> test(ptr);
    //теперь значение ptr равно NULL_PTR
    //объект принадлежит сильному указателю
    //а вызывающая сторона 
    //не имеет к нему прямого доступа
 
    EndProgramm();
}

Проблема в том, что я хочу сохранив инвариант сильного указателя, при этом иметь возможность написать вот так:
C++
1
2
3
4
5
6
7
int main()
{
    TSharedPointer<int> test(new int()  );  
    
  
    EndProgramm();
}
Компилятор мне на это пишет:

error C2664: TSharedPointer<TypeT>::TSharedPointer(TypeT *&): невозможно преобразовать параметр 1 из 'int *' в 'int *&'

Вопрос: как сохранить возможность обнуления входящих указателей, но при этом иметь возможность скармливать интеллектуальному указателю оператор new ?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.11.2011, 10:31
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Не хватает знаний. Не знаю, как на с++ реализовать возможность (C++):

Реализовать двусвязный список. В разных узлах одного списка может быть любой объект одного из допустимых типов (своих знаний не хватает) - C++
Вобщем делаю тестовые задания. На одно мне даже ответили, результат отрицательный. Помогите понять если кто поймёт его не так как я или...

Не знаю как реализовать - C++
Итак, пользователь может ввести, а может и ничего не вводить, но програма выводит число через каждые sleep(500) как реализировать...

Возможность доработки ERP системы без соответствующих знаний - C++
Подскажите пожалуйста, заказывал у разработчика ERP систему для себя, но вышло так что человек просто пропал. А сейчас возникла острая...

Не знаю как реализовать.Само задание в изображении. Работа с файлами - C++
Помогите пожалуйста, хотя бы как сделать так, чтобы считались строчки, которые заканчиваются буквой с клавиатуры.

Не знаю как реализовать чтение из файла/запись в файл с особыми условиями - C++
Добрый день! У меня есть файл file.txt с таким содержанием: xxx /x qqq zzz /z aaa ccc /c

Игра в кости: реализовать мини-казино; реализовать возможность игры 2 человек между собой - C++
Уважаемые форумчане! Подскажите, пож-та, где можно посмотреть программу игры в кости, но не человека и компьютера, а двух человек...

67
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
15.11.2011, 15:15 #16
Bers, Не обнулит.

C++
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <boost/shared_ptr.hpp>
 
int main()
{
   int* pointer = new int(5);
   boost::shared_ptr<int> ptr(pointer);
   std::cout << *pointer << std::endl;
}
Добавлено через 34 секунды
http://liveworkspace.org/code/9002825d3c3cffc992ec59bc80aebaf2

И ни один smart_pointer таким не занимается. Это не логично.
0
Bers
Заблокирован
15.11.2011, 15:17  [ТС] #17
Цитата Сообщение от ForEveR Посмотреть сообщение
Это не логично.
В умной книжке читал: инструмент должно быть легко использовать правильно. И затрудненно неправильно.

почему не логично?
0
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
15.11.2011, 15:20 #18
Bers, Да потому что. Человек создал указатель. Подал его в smart_pointer. А потом захотел использовать так, без вызова get() и получил бабах. Не красиво.
Ну и плюс к тому бустовские смарты могут использоваться далеко не только с new.
0
Bers
Заблокирован
15.11.2011, 15:20  [ТС] #19
Цитата Сообщение от ForEveR Посмотреть сообщение
И ни один smart_pointer таким не занимается. Это не логично.

Кстати, идею обнулять оригинал при изъятии у него права владения, я подглядел у стд::ауто_птр
0
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
15.11.2011, 15:21 #20
Bers, std::auto_ptr не присутствует в новом стандарте. Вместо него shared/weak/scoped etc.
0
silent_1991
Эксперт С++
4985 / 3042 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
15.11.2011, 15:23 #21
Цитата Сообщение от Bers Посмотреть сообщение
я подглядел у стд::ауто_птр
Который таким тоже не занимается.

Добавлено через 1 минуту
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <memory>
 
int main()
{
   int *ptr = new int(42);
   std::auto_ptr< int > aptr(ptr);
 
   std::cout << *ptr << std::endl;
 
   return 0;
}
0
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
15.11.2011, 15:23 #22
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
      /**
       *  @brief  An %auto_ptr is usually constructed from a raw pointer.
       *  @param  p  A pointer (defaults to NULL).
       *
       *  This object now @e owns the object pointed to by @a p.
       */
      explicit
      auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
 
      /**
       *  @brief  An %auto_ptr can be constructed from another %auto_ptr.
       *  @param  a  Another %auto_ptr of the same type.
       *
       *  This object now @e owns the object previously owned by @a a,
       *  which has given up ownership.
       */
      auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
 
      /**
       *  @brief  An %auto_ptr can be constructed from another %auto_ptr.
       *  @param  a  Another %auto_ptr of a different but related type.
       *
       *  A pointer-to-Tp1 must be convertible to a
       *  pointer-to-Tp/element_type.
       *
       *  This object now @e owns the object previously owned by @a a,
       *  which has given up ownership.
       */
      template<typename _Tp1>
        auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }
Да кстати.
0
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 16:22 #23
Касательно того, почему вызывается константный.
Локальные безымянные объекты можно передавать только по константной ссылке, т.к. сразу после выхода из функции они будут разрушены и все изменения в них потеряются. Более того, компилятор выдаёт предупреждение по поводу ссылок на безымянные объекты.
1
Bers
Заблокирован
15.11.2011, 16:24  [ТС] #24
Deviaphan, а по поводу кода, который предложил Forever ?
Он безопасен? Никаких проблем не будит из-за конст_каст?
0
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 16:33 #25
Цитата Сообщение от Bers Посмотреть сообщение
Он безопасен? Никаких проблем не будит из-за конст_каст?
Теоретически безопасен.
На практике всё что угодно может быть. Причём в любом коде.)
Тут уже совершенно верно заметили, что обнулять указатель не стоит.

Ещё у кого-то, не помню у кого (возможно у Маейрса, но кажется не у него) встречал рекомендацию использовать ссылки только для передачи констант. Если нужно вернуть изменённый объект, то передавать указатель. Мне это не кажется удобным и никогда этой рекомендации не следовал, но совет обоснованный. Невозможно случайно передать объект на изменение. И сразу видно, что если объект передаётся по указателю, то он будет изменяться, и не нужно смотреть прототип.
0
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
15.11.2011, 16:41 #26
Bers, В теории да. Но он допускает такой момент.

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
#include <iostream>
#include <stdexcept>
 
template<class T>
class Pointer
{
public:
   Pointer(T*& obj)
   {
      object = obj;
   }
   Pointer(const T* obj)
   {
      object = const_cast<T*>(obj);
      *object = 5;
   }
   const T& operator *()
   {
      if (object)
      {
         return *object;
      }
      throw std::logic_error("Dereference of null pointer");
   }
private:
   T* object;
};
 
int main()
{
   const int* const cptr = new int(15);
   Pointer<int> p1(cptr);
   std::cout << *cptr << std::endl;
}
Добавлено через 2 минуты
А более опасны такие варианты. Но всякий бред предусмотреть невозможно.

C++
1
2
3
4
5
6
7
8
9
10
int main()
{
   const int* const cptr = new int(15);
   Pointer<int> p1(cptr);
   std::cout << *cptr << std::endl;
   const int& value = 10;
   const int* cptr2 = &value;
   Pointer<int> p2(cptr2);
   std::cout << value << std::endl;
}
1
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 16:43 #27
Цитата Сообщение от ForEveR Посмотреть сообщение
const int& value = 10;
о_0 и скомпилировало?
0
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
15.11.2011, 16:44 #28
Deviaphan, Вполне. И изменило.
0
Bers
Заблокирован
15.11.2011, 16:47  [ТС] #29
Цитата Сообщение от Deviaphan Посмотреть сообщение
Тут уже совершенно верно заметили, что обнулять указатель не стоит.
Этого не достаточно. Нужно понять почему, и в чем глобальная разница?
Если я не обнулил - я могу сломать всю работу. А что бы не сломать - я не должен с этим указателем дальше работать. Вместо него я должен пользовать интеллектуальный.

Если я обнулил - я просто не смогу уже его пользовать. И мне придётся пользоваться интеллектуальным.

Так в чем тогда принципиальная разница? Кроме той, что мой смартпоинтер более безопасный?

Цитата Сообщение от Deviaphan Посмотреть сообщение
Если нужно вернуть изменённый объект, то передавать указатель.
Буквально вчера-позавчера на этот самом форуме был человек, который попросил помочь найти ошибку. Ошибка была в том, что он передавал указатель, желая получить обратно измененный объект. Результат: внутри пересоздавался объект, но модифицировалась копия указателя, а не ссылка. Поэтому, когда функция отрабатывала, и управление возвращалось обратно - там попрежнему действовал старый оригинальный указатель, который уже указывал на чужую память.

Лично я, что бы запретить изменения объектов пользуюсь модификаторами const
0
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 16:50 #30
Я в шоке, честно говоря. Допустим, что 10 было записано в блоке данных и адрес у неё всё-таки получился. Но при изменении должна была быть ошибка доступа, т.к. память ReadOnly.
Ацтойный косяк, однако.

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
Результат: внутри пересоздавался объект, но модифицировалась копия указателя, а не ссылка
Я имел в виду, передавать указатель на изменяемый объект. Если изменяемый объект это указатель, нужно передавать указатель на указатель. Точно так же, как ты передаёшь ссылку на указатель.
1
15.11.2011, 16:50
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.11.2011, 16:50
Привет! Вот еще темы с ответами:

Числа считаются равными если они отличаются не более, чем на (10^-12) / c++ / как реализовать эту возможность? - C++
На плоскости заданы три точки А, В и С. Определить, какая из двух последних точек (B или C) расположена ближе к A, и вывести расстояние от...

Выручайте, знаний не хватает - VBA
Доброго всем дня. Пытался решить практическую задачу. Заключается она в своевременном сигнализировании о готовности всех комплектующих,...

Не хватает знаний. Выбор между ноутом и стационар - Офисный компьютер
Здравствуйте, друзья. В общем хочу себе купить компьютер. Бюджет около 420 у.е. (плюс минус - но лучше минус 8-)) Собственно выбор...

Не знаю как реализовать - PHP
Требуется сделать поиск без перезагрузки страницы, то есть: Вбиваешь в поиск и сразу результаты, меняешь страницу (LIMIT 0,10) и к 0...


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru