Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
0 / 0 / 0
Регистрация: 20.04.2020
Сообщений: 11

Shared_ptr и парадигма CoW

20.04.2020, 22:54. Показов 3448. Ответов 42
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Задача:
Написать простенький аналог shared_ptr применяя парадигму Copy on Write.

Проблема:
Не могу понять в какой момент дергать функцию создания данных и как правильно это сделать.
Как реализовать функции void ensureInitialized() const и void ensureUnique().

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include "datahandler.h"
 
using namespace std;
 
DataHandler::DataHandler(const DataHandler &h)
{
    if (data == h.data)
        return;
    if (h.data == nullptr)
        return;
    if (h.refCounter == nullptr)
        return;
 
    (*h.refCounter)--;
 
    if((*h.refCounter) == 0)
    {
        delete h.refCounter;
        delete h.data;
    }
 
    data = h.data;
    refCounter = h.refCounter;
    (*refCounter)++;
}
 
DataHandler::~DataHandler()
{
    if (refCounter == nullptr)
        return;
 
    (refCounter)--;
 
    if((*refCounter) == 0)
    {
        delete refCounter;
        delete data;
    }
    refCounter = 0;
    data = 0;
}
 
Data* DataHandler::operator ->()
{
    return data;
}
 
const Data* DataHandler::operator ->() const
{
    ensureInitialized();
    return data;
}
 
void DataHandler::ensureInitialized() const
{
    if (data == nullptr)
    {
 
        Data temp;
        *data = temp;
    }
}
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#ifndef DATAHANDLER_H
#define DATAHANDLER_H
 
#include <iostream>
 
using namespace std;
 
// Отвечает за хранение, создание и удаление наших ресурсов.
// Указатель на выделенный буфер, размер строки и тд. - все тут.
class Data
{
public:
    Data() {cout << "Data created\n";} // выделяем память
    Data(const Data&) {cout << "Data copied\n";} // делаем полную копию
    ~Data() {cout << "Data deleted\n";} // подчищаем
 
    void read() const {cout << "Data read() \n";}
    void write() {cout << "Data write() \n";}
};
 
// Отвечает за разделение ресурсов и ленивую инициализацию.
class DataHandler
{
public:
    DataHandler() = default;
    // Если у h есть данные, привязываемся к ним,
    // не забываем про счетчик ссылок. Можно еще по аналогии оператор "="
    // перегрузить.
    DataHandler(const DataHandler &h);
    // Если держим данные, уменьшаем счетчик ссылок, если больше никто на
    // эти данные не ссылается - удаляем.
    ~DataHandler();
 
    // Убеждаемся, что данные есть и спокойно возвращаем.
    const Data *operator ->() const;
    // Убеждаемся, что данные уникальны и спокойно возвращаем.
    Data *operator ->();
 
private:
    mutable int *refCounter; // указатель на счетчик ссылок
    mutable Data *data = nullptr;
 
    // Проверяем, держим ли мы данные, если нет - создаем.
    void ensureInitialized() const;
    // Проверяем, что на эти данные (если они вообще есть) никто кроме
    // нас не ссылается, если нет - создаем себе копию.
    void ensureUnique();
};
 
#endif
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
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
 
#include "datahandler.h"
 
using namespace std;
 
// Пример использования нашего умного DataHandler`a в другом
// классе. У вас его будет использовать MyString.
class DataUser 
{
public:
    void read() const {dataHandler->read();}
    void write() {dataHandler->write();}
 
private:
    DataHandler dataHandler;
};
 
int main()
{
    // Ничего не происходит, у нас же ленивая инициализация.
    DataUser du1; 
    
    // Создали данные и обратились к ним на чтение.
    du1.read(); 
    
    // Привязываемся к созданным данным.
    DataUser du2(du1);
    
    // Новые данные не создаются, т. к. обращение на чтение.
    du2.read();
 
    // Идет обращение на запись, поэтому сначала создаем себе
    // копию.
    du2.write();
}
 
// Вывод:
// Data created
// Data read() 
// Data read() 
// Data copied
// Data write() 
// Data deleted
// Data deleted
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.04.2020, 22:54
Ответы с готовыми решениями:

Сложный калькулятор на обратной польской (импиративная парадигма)
Доброго времени суток! Задание, написать сложный калькулятор не используя ООП Сделал на основе своего &quot;стека&quot;, все методы...

Парадигма программирования php
Здравствуйте. Есть разработанный сайт на PHP. Пользовательский интерфейс+админка. Сам сайт - справочно-информационная система....

Чистота Haskell и функциональная парадигма
Мне очень интересна и приятна эта парадигма, но накопилось несколько вопросов. Первый, идея про отсутствие побочных эффектов пошла из...

42
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
21.04.2020, 16:31
Студворк — интернет-сервис помощи студентам
Ailuropoda, и еще немного о указателях. Дело в том, что указатели это не те парни которые поддерживают CoW. От них этого, здоровые люди не ожидают. CoW поддерживают типы с семантикой значений. Есть крутые программисты с очень большим техническим уровнем, которые просто не понимают, что они делают и почему. Не будем их в этом винить.
Однако семантика значений это природная вещь идущая от С, где каждая новая переменная создаётся как копия. CoW это мудрая корова, которая говорит: "И не лень вам копировать молоко, когда вы его только наблюдаете?". То есть, у крупной скотины рога растут именно из головы. Она говорит о том, что ленивый способ создания копии - легче. Копируй когда будешь пить, а пока смотришь - можно смотреть и совместно с другими зрителями (созерцателями - то есть со-наблюдателями).
А вот указатели, это в принципе способ работы без копий. Представьте себе, что однажды вы проснулись в мире, где сырые указатели стали делать новую копию объекта-цели, при изменении последнего. Это же именины сердца представить себе цикл:
C++
1
while(*charPointerToCStr++)*charPointerToCStr='A' ;//каждый раз в другое место...

Это главная причина того, ущерб наносимый вашим преподом от совмещения данных тем уже компенсирован тем, что боженька уже сделал с его мозгом.
Вам советую почитать Effective C++ Мейерса, где он говорит о реализации CoW класса. Там shared_ptr используется как указатель на данные - поле класса. То есть он внутри и является частью реализации, а не наоборот.
https://savepearlharbor.com/?p=290541#id-1-4
тут например есть раздел: 2.1. Копирование при записи
там в ссылках найдёте ряд источников. И сам текст тоже вполне годный.

Добавлено через 5 минут
Ailuropoda, не злите препода. Таких людей лучше не трогать. Сделайте класс реализующий CoW, назовите умным указателем и не спорьте. Нет смысла спорить.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13214 / 6847 / 1825
Регистрация: 18.10.2014
Сообщений: 17,333
21.04.2020, 17:45
Цитата Сообщение от hoggy Посмотреть сообщение
ты используешь слово "невозможно" для вполне осуществимых вещей.
даже после того, как тебя ткнут рожей в рабочий код.
Лол! Да хоть в рабоче-крестьянский! Куда нам, ентеллехентам-неосиляторам!

Это, однако, нисколько не отменяет того факта, что никакого CoW для абстрактного указателя нет и быть не может, кроме разве что в твоем воображении, среди влажных фантазий о "тыканьи рожей" и "рабочем коде".
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
21.04.2020, 18:00
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
что никакого CoW для абстрактного указателя нет и быть не может
Хотя бы по тому что в результате любых возможных телодвижений в этом направлении, то что получится - это семантически будет уже ни разу не CoW, и не разу не указатель. Хотя бы потому что семантика CoW (совмещение нескольких инстансов в одном буфере, c автоматическим определением для какого инстанса нужно выделить отдельный буфер) абсолютно противоположна семантике указателя (доступ к одному и тому же инстансу).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
21.04.2020, 18:00

COW copy on write, класс MyString
Нужно реализовать COW, но никак все не получается main.cpp #include &lt;iostream&gt; #include &quot;mystring.h&quot; using...

Описать класс Cow, который наследуется от класcа Animal
Нужно написать класс Cow, который наследуется от класcа Animal. Класс Animal имеет метод getName (name можно передать в конструктор). Класс...

Написать класс Cow, который наследуется от класcа Animal
Попросили помочь найти решение, а я даже не знаю куда обратиться. Нужно написать класс Cow, который наследуется от класcа Animal....

Создаем объект cow, у которого есть метод message, который принимает аргументом text и возвращает его
Создаем объект cow, у которого есть метод message, который принимает аргументом text и возвращает его. Создаем 2 блока try catch: ...

Создать абстрактный базовый класс Animal и производные классы Rooster, Goose, Turkey, Duck, Goat, Ram, Cow, Horse
Здравствуйте, не могу допереть как сделать последний пункт задания.Вот само задание 1. Создать абстрактный базовый класс Animal с чистой...


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

Или воспользуйтесь поиском по форуму:
43
Ответ Создать тему
Новые блоги и статьи
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
Запись в регистр сведений независимо от заполненности табличной части
Maks 25.08.2026
Реализация из решения ниже выполнена на нетиповом документе с несколькими табличными частями, разработанного в КА2. Задача: Обеспечить запись документа в регистр сведений независимо от. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru