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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.74
Bers
Заблокирован
15.11.2011, 10:31     Не хватает знаний. Не знаю, как на с++ реализовать возможность #1
Есть одна вещь, которую у меня сделать никак не получается.

В моей старенькой 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 ?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.11.2011, 10:31     Не хватает знаний. Не знаю, как на с++ реализовать возможность
Посмотрите здесь:

Реализовать двусвязный список. В разных узлах одного списка может быть любой объект одного из допустимых типов (своих знаний не хватает) C++
C++ Доработка программы: реализовать возможность работы с шестнадцатеричными числами
Возможность доработки ERP системы без соответствующих знаний C++
Не знаю как реализовать C++
Не знаю как реализовать чтение из файла/запись в файл с особыми условиями C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 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;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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()) { }
Да кстати.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 16:22     Не хватает знаний. Не знаю, как на с++ реализовать возможность #23
Касательно того, почему вызывается константный.
Локальные безымянные объекты можно передавать только по константной ссылке, т.к. сразу после выхода из функции они будут разрушены и все изменения в них потеряются. Более того, компилятор выдаёт предупреждение по поводу ссылок на безымянные объекты.
Bers
Заблокирован
15.11.2011, 16:24  [ТС]     Не хватает знаний. Не знаю, как на с++ реализовать возможность #24
Deviaphan, а по поводу кода, который предложил Forever ?
Он безопасен? Никаких проблем не будит из-за конст_каст?
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 16:33     Не хватает знаний. Не знаю, как на с++ реализовать возможность #25
Цитата Сообщение от Bers Посмотреть сообщение
Он безопасен? Никаких проблем не будит из-за конст_каст?
Теоретически безопасен.
На практике всё что угодно может быть. Причём в любом коде.)
Тут уже совершенно верно заметили, что обнулять указатель не стоит.

Ещё у кого-то, не помню у кого (возможно у Маейрса, но кажется не у него) встречал рекомендацию использовать ссылки только для передачи констант. Если нужно вернуть изменённый объект, то передавать указатель. Мне это не кажется удобным и никогда этой рекомендации не следовал, но совет обоснованный. Невозможно случайно передать объект на изменение. И сразу видно, что если объект передаётся по указателю, то он будет изменяться, и не нужно смотреть прототип.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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;
}
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 16:43     Не хватает знаний. Не знаю, как на с++ реализовать возможность #27
Цитата Сообщение от ForEveR Посмотреть сообщение
const int& value = 10;
о_0 и скомпилировало?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
15.11.2011, 16:44     Не хватает знаний. Не знаю, как на с++ реализовать возможность #28
Deviaphan, Вполне. И изменило.
Bers
Заблокирован
15.11.2011, 16:47  [ТС]     Не хватает знаний. Не знаю, как на с++ реализовать возможность #29
Цитата Сообщение от Deviaphan Посмотреть сообщение
Тут уже совершенно верно заметили, что обнулять указатель не стоит.
Этого не достаточно. Нужно понять почему, и в чем глобальная разница?
Если я не обнулил - я могу сломать всю работу. А что бы не сломать - я не должен с этим указателем дальше работать. Вместо него я должен пользовать интеллектуальный.

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

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

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

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

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
Результат: внутри пересоздавался объект, но модифицировалась копия указателя, а не ссылка
Я имел в виду, передавать указатель на изменяемый объект. Если изменяемый объект это указатель, нужно передавать указатель на указатель. Точно так же, как ты передаёшь ссылку на указатель.
Bers
Заблокирован
15.11.2011, 17:01  [ТС]     Не хватает знаний. Не знаю, как на с++ реализовать возможность #31
Цитата Сообщение от ForEveR Посмотреть сообщение
В теории да. Но он допускает такой момент.
Цитата Сообщение от ForEveR Посмотреть сообщение
А более опасны такие варианты. Но всякий бред предусмотреть невозможно.
Ну это да, это я согласен. Не во всех случаях он сможет обнулить входящий указатель.
Но с другой стороны.. это все таки лучше, чем совсем ничего.

Ну а так вообще, по логике - указатель константный. Он и не должен его обнулять. Он же константный!
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 19:54     Не хватает знаний. Не знаю, как на с++ реализовать возможность #32
Не путай константный указатель и указатель на константу. Здесь - указатель на константу.

Добавлено через 2 часа 51 минуту
Вспомнил. То было цитирование не Майерса, а Стивена Дьюхерста. Книжку звать "С++. Священные знания". Забавная книжка.)
Bers
Заблокирован
15.11.2011, 20:04  [ТС]     Не хватает знаний. Не знаю, как на с++ реализовать возможность #33
C++
1
2
const int& value = 10;
const int* cptr2 = &value;
сколько не втыкал, так ничего криминального и не увидил
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 20:10     Не хватает знаний. Не знаю, как на с++ реализовать возможность #34
А вот если cptr2 консткастоп привести к не константному указателю и попробовать изменить значение...

Добавлено через 3 минуты
Вообще странно. Я бы на месте программы упал с исключением по изменению памяти в блоке данных. Видимо, надо код смотреть. Или я не правильно понимаю, в какое место он константу 10 сохраняет.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
15.11.2011, 20:26     Не хватает знаний. Не знаю, как на с++ реализовать возможность #35
Deviaphan, Если переменную объявлять не как ссылку - то не изменит.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
15.11.2011, 20:42     Не хватает знаний. Не знаю, как на с++ реализовать возможность #36
Цитата Сообщение от ForEveR Посмотреть сообщение
Если переменную объявлять не как ссылку - то не изменит.
Вот именно в этом варианте интересно. Т.е. по идее у "магического числа" и адреса быть не должно. Но раз есть, значит оно где-то записано. Получается, что не в секции данных, а как обычная переменная. Причём не помечена как константа, раз ошибки доступа нет. Я сейчас пробовал уронить, норм всё отработало. И вот теперь думаю, в каком месте я не прав и как оно на самом деле работает.)
Bers
Заблокирован
16.11.2011, 02:37  [ТС]     Не хватает знаний. Не знаю, как на с++ реализовать возможность #37
C++
1
2
3
4
5
const int& value = 10;
    const int* cptr2 = &value;
    TSharedPointer<int> p2(cptr2); //ассерт на попытку убить объект. В релизе молчком
    std::cout << value << std::endl;
    (*p2)=100; //Молча меняет значение константы value на 100
Получается, что есть лазейка, через которую можно засунуть в сильный указатель бомбу.

Кстати! А как стандартные (бустовские) указатели отреагируют, если им скормить константные исходные данные?


Мне почему то кажется, что с таким средством как конст_каст можно любой самый надежный класс довести до анархии.
Когда класс уже точно не знает, например... можно данный объект вообще убивать, или нельзя? Не удалил - утечка, удалил - взорвался.

Если была возможность запретить сильному указателю принимать на входе вот такую ересь
C++
1
2
 const int& value = 10;
    const int* cptr2 = &value;
И вообще, констатные указатели, и указатели на константу. Пусть работает с обычными константами..
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
16.11.2011, 06:12     Не хватает знаний. Не знаю, как на с++ реализовать возможность #38
Цитата Сообщение от Bers Посмотреть сообщение
Кстати!
От обезьяны с гранатой никто не застрахован.
C++
1
2
int a;
std::shared_ptr<int> ptr(&a);
Bers
16.11.2011, 06:51  [ТС]
  #39

Не по теме:

Deviaphan, у меня отказалась студия апгредиться. Есть подозрение - из-за того что она русская.

Конкретно мне хочется разжиться стандартизированными указателями.

Можно ли как нибудь её проапгрейдить в ручную? Ну допустим, тупо скопировав стандартную библиотеку?

А если можно, не знаете где можно отдельно от студии достать std ?
(стандартную библиотеку, а не пространство имён, если кто опять не понял)

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.11.2011, 07:05     Не хватает знаний. Не знаю, как на с++ реализовать возможность
Еще ссылки по теме:

Числа считаются равными если они отличаются не более, чем на (10^-12) / c++ / как реализовать эту возможность? C++
C++ Не знаю как реализовать.Само задание в изображении. Работа с файлами

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

Или воспользуйтесь поиском по форуму:
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
16.11.2011, 07:05     Не хватает знаний. Не знаю, как на с++ реализовать возможность #40
Цитата Сообщение от Bers Посмотреть сообщение
Можно ли как нибудь её проапгрейдить в ручную? Ну допустим, тупо скопировав стандартную библиотеку?
Можно. Вся std это шаблонная библиотека, т.е. весь её код в хэдэрах.
Но тогда уж лучше сразу портабл ставь, заодно лицензионных прав майкрософта не нарушишь.)

На Английскую версию все сервис паки без вопросов ставились, так что скорее всего из-за Русского, да.

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
Конкретно мне хочется разжиться стандартизированными указателями.
Используй буст.) Он "стандартнее", чем студия. И совместимость не потеряешь.
Yandex
Объявления
16.11.2011, 07:05     Не хватает знаний. Не знаю, как на с++ реализовать возможность
Ответ Создать тему
Опции темы

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