Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.78/18: Рейтинг темы: голосов - 18, средняя оценка - 4.78
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
1

Чем заменить указатель

05.07.2020, 10:39. Показов 3709. Ответов 48
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Чем заменить можно указатель в данном примере. Что бы можно было использовать p как объект без операции разыменования?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <queue>
 
class SomeСlass
{
private:
    using Container = std::queue<int>;
    Container * p;
 
public:
    SomeСlass() : p{nullptr} {}
    SomeСlass(Container & r) : p{&r} {}
 
    void Reset(Container & r)
    {
        p = &r;
    }
};
Добавлено через 6 минут
подозреваю, что использовать указатель в данном случае оптимальное и единственное решение, можно было бы использовать ссылку Container & если бы не было функции члена Reset
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.07.2020, 10:39
Ответы с готовыми решениями:

Указатель или ссылка на указатель. В чем разница?
Есть вопрос про указатели и ссылки на указатели :scratch: Хочу в функциях f1() и в f2()...

Чем отличаются указатель на строку и константный указатель на строку?
Просто обьясните, как такое возможно? char *a=&quot;fff&quot;; В чем отличие от этого? : const char...

Указатель на указатель, в чем смысл?
BOOL WTSEnumerateProcesses( _In_ HANDLE hServer, _In_ DWORD Reserved, _In_ DWORD...

сма DAEWOO DWD M1029A чем заменить транс, трансформатор в обрыве, чем заменить
день добрый. модуль PN:361430A950 первичная транса в обрыве . может кто подскажет параметры ,...

48
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
05.07.2020, 16:34  [ТС] 21
Author24 — интернет-сервис помощи студентам
Undisputed, Avazart, hoggy, спасибо за участие
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
05.07.2020, 16:40 22
_stanislav, Тут в общем вопрос касательно взаимосвязей в ООП по большому счету. Их два вида - композиция - обьект является составной частью и уничтожается вместе с хозяином, и агрегация -объект является составной частью другого объекта, ваш же объект только пользуется им в случае если такой есть - т.е. помереть может собственной смертью вне зависимости от ваших на него ссылок . Вы тут используете агрегацию. Т.е. по определению должны быть готовы к тому что кто то сторонний может уничтожить объект на который вы ссылаетесь. Разрулить ситуацию можно двумя вариантами - либо действительно weak_ptr (цена - лок при каждом обращении) либо интрузивные двунаправленные указатели (цена - более сложная реализация, в универсальном варианте - оверхед по памяти указателей от 2x, но оповещение о смерти объекта однократное).
Ну либо пересмотреть архитектуру в направление композиции очереди в ваш объект/обращения к очереди через ее хозяина.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
05.07.2020, 16:41 23
Можно к примеру так использовать
C++
1
SomeСlass some(new Container);
Подразумевая передачу владения и тогда уместен unique_ptr.
Или когда у нас Containe расшаривается между несколькими SomeСlassX и тогда соответственно shared_ptr.
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
05.07.2020, 17:07  [ТС] 24
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Т.е. по определению должны быть готовы к тому что кто то сторонний может уничтожить объект на который вы ссылаетесь.
пока нет в этом нужды

Добавлено через 3 минуты
Класс который передает в SomeСlass буфер, заинтересован в том что бы SomeСlass обработал этот буфер, зачем ему затирать буфер? Вообщем то класс который передает в SomeСlass буфер только и делает что заполняет этот буфер и передает на обработку в SomeСlass

Добавлено через 22 минуты
точнее некий класс буферезирует данные которые SomeСlass уже использует через указатель.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.07.2020, 17:10 25
Цитата Сообщение от Undisputed Посмотреть сообщение
std::stack:op не делается проверка на то что есть ли элемент в стеке или нет. Это как бы оставляют на конечного пользователя тем самым не создают оверхед но при этом оставляют конечному пользователю возможность сделать эту проверку самому хотя они могли бы например возвращать bool как результат операции удаления типа удалилось или нет и не вводить UB если контейнер окажется пустым (вот что я имел ввиду когда говорил про оверхед при навязывании безопасного обращения с объектами).
не понятно, нафиг нужен этот буль.

уважающая себя, хорошо воспитанная программа не должна делать бессмысленных вещей.

если очередь пуста, тогда в принципе ничего удалять из неё не нужно.

Кликните здесь для просмотра всего текста

фрагмент из реального продакшен кода.
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
    bool task_queue::run_once()
    {
        task_queue::task task;
        {
            ::std::lock_guard<decltype(this->m_mutex)>
                lock(this->m_mutex);
 
            if(!this->m_tasks.empty())
            {
                task = ::std::move(this->m_tasks.front());
                this->m_tasks.pop();
            }
            else
                return false;
        }
 
        try
        {
            task();
        }
        catch(const ::std::exception& e)
        {
            this->error(e.what());
        }
        catch(...)
        {
            this->error("unknown exception");
            assert(0 && "unknown exception");
        }
        return true;
    }


как у тебя вообще, хотя бы чисто теоретически может возникнуть ситуация,
когда ты вынужден опираться на этот буль?
вот объясни мне: как это вообще возможно?

ты что, пишешь код по принципу: "сначала делаем, и только потом думаем?"

C++
1
2
ты копай тут, а ты - тут, и тут. а я пока пойду, и узнаю, где нужно копать
(ц) армейский юмор.

Цитата Сообщение от Undisputed Посмотреть сообщение
Что касается того что "ресурс всегда должен быть валидным когда он нужен и если его нет то это программная ошибка и weak_ptr не поможет" то тут я не согласен. Мы ведь может вызвать use_count для weak_ptr при уточнённом объекте на который был нацелен соответствующий shared и это не будет UB и никаких программных ошибок не будет. Если use_count == 0, можем бросить эксепшен.
здрасти-приехали.

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

у тебя ошибка в коде из-за которой алгоритм в принципе не функционирует.
вот бросил ты эксепшен и что?
что дальше?

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




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


не будет он работать.
0
6107 / 3461 / 1406
Регистрация: 07.02.2019
Сообщений: 8,794
05.07.2020, 17:39 26
Цитата Сообщение от _stanislav Посмотреть сообщение
Вообщем то класс который передает в SomeСlass буфер только и делает что заполняет этот буфер и передает на обработку в SomeСlass
А не лучше ли тогда и передавать владение(std::move или через unique_ptr, если контейнер не поддерживает семантику перемещения), и забрать после?
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
05.07.2020, 17:44  [ТС] 27
Цитата Сообщение от zayats80888 Посмотреть сообщение
А не лучше ли тогда и передавать владение
оверхед
Цитата Сообщение от zayats80888 Посмотреть сообщение
если контейнер не поддерживает семантику перемещения
unique поддерживает семантику перемещения
0
6107 / 3461 / 1406
Регистрация: 07.02.2019
Сообщений: 8,794
05.07.2020, 17:47 28
Цитата Сообщение от _stanislav Посмотреть сообщение
оверхед
Да я бы не сказал, зато при добавлении многопоточности меньше рефакторить, имхо.
Цитата Сообщение от _stanislav Посмотреть сообщение
unique поддерживает семантику перемещения
А я о чём?
0
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
05.07.2020, 17:47 29
Цитата Сообщение от hoggy Посмотреть сообщение
если очередь пуста, тогда в принципе ничего удалять из неё не нужно.
я понимаю о чем ты говоришь и в целом то что ты говоришь это как раз хорошо в плане гибкости - то есть мы сами решаем делать проверку или нет (т.е нас не кто не обязывает на постоянной основе делать проверки)... но тем не менее, отвечая на твой вопрос
Цитата Сообщение от hoggy Посмотреть сообщение
нафиг нужен этот буль
можно написать такой код:
C++
1
if (stack.pop()){std::cout << "Removed";}
этот код проще чем аналогичный ему по смыслу такой вот код:
C++
1
2
3
4
if(!stack.empty()) {
    stack.pop();
    std::cout << "Removed";
}
вот для упрощения кода например этот буль может быть нужен
и прежде чем ты назовешь этот код плохим названием скажу что я в этой теме не защищаю какой либо подход
а лишь рассматриваю в принципе возможные варианты, их плюсы и минусы

Цитата Сообщение от hoggy Посмотреть сообщение
твой класс должен обработать данные, которые внезапно протухли.
если это ситуация где подобного не должно быть то да, это уже баг
но если скажем твой ресурс это некий endpoint, который не спрашивая тебя может закрыть соединение с тобой, то это уже не баг. и вот мы как бы можем проверить а открыто ли еще соединение. если да - то работаем. если нет - то не работаем. и это нормально в рамках нашей задачи.
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
05.07.2020, 17:55  [ТС] 30
Цитата Сообщение от zayats80888 Посмотреть сообщение
Да я бы не сказал, зато при добавлении многопоточности меньше рефакторить, имхо.
интересно

Добавлено через 3 минуты
zayats80888, для большей универсальности класса SomeClass лучше наверное принимать буфер по значению с перемещением.

Добавлено через 3 минуты
Цитата Сообщение от _stanislav Посмотреть сообщение
для большей универсальности класса SomeClass лучше наверное принимать буфер по значению с перемещением.
что бы зацепление ослабить
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.07.2020, 18:24 31
Цитата Сообщение от Undisputed Посмотреть сообщение
if (stack.pop()){std::cout << "Removed";}
по-моему, это - какой то бред.
такое впечатление, что автору кода совершенно пофигу:
будет ли в итоге удален элемент, или нет.
всвязи с чем совершенно не понятно:
зачем вообще он пытается удалить элемент из очереди?

Цитата Сообщение от Undisputed Посмотреть сообщение
if(!stack.empty()) {
    stack.pop();
    std::cout << "Removed";
}
дело не в том: проще или нет.
дело в здравом смысле.
дело в ответе на вопрос: зачем удаляем?

здесь по смыслу - все тоже самое, что и в первом варианте.


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

ещё раз:
сначала выясняем: а нужно ли вообще обрабатывать?
и только потом удаляем кандидат-отработанный элемент.


удалять просто ради удаления - это какой то бред.


Цитата Сообщение от Undisputed Посмотреть сообщение
если это ситуация где подобного не должно быть то да, это уже баг
все ситуации, где нужна ссылочная семантика, но не нужен шаринг,
попадают под вариант с багом.

все без исключения.
во всех в этих ситуациях ссылка должна оставаться валидной.
иначе алгоритм в принципе не сможет работать.
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
05.07.2020, 18:34  [ТС] 32
вот объявление класса SomeClass если кому интересно:
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#pragma once
 
#include <string>
#include <queue>
#include <forward_list>
 
#include "Token.h"
#include "LexemeState.h"
#include "TableOfSymbols.h"
 
namespace clc::prs::lxr
{
    class Lexer
    {
    private:
        using WChar = std::wstring::value_type;
 
        LexemeState lexemeState;
        std::queue<WChar> * expression;
 
        TableOfSymbols<> tableOfSymbols;
 
        TokenEnum pastToken{Empty};
        bool IsUnary(TokenEnum);
 
        Token RefineToken(TokenEnum, std::wstring &);
 
        TokenEnum RefineFunction(std::wstring &);
        TokenEnum RefineOperation(WChar);
 
        std::forward_list<std::wstring> functionNames;
 
    public:
        Lexer();
        Lexer(std::queue<WChar> &, std::initializer_list<std::wstring> l =
                {L"sin", L"cos", L"tan", L"sqrt",} );
 
        Lexer(Lexer const &) = delete;
        Lexer(Lexer &&) = default;
 
        ~Lexer() = default;
 
        Lexer & operator=(Lexer const &) = delete;
        Lexer & operator=(Lexer &&) = default;
 
        Token GetToken();
 
        void Reset(std::queue<WChar> &);
        operator bool();
 
        TableOfSymbols<> & GetTableOfSymbol();
    };
 
    inline Lexer::Lexer() : expression{nullptr} {}
 
    inline Lexer::Lexer(
        std::queue<WChar> & i,
        std::initializer_list<std::wstring> l) :
            expression{&i},
            functionNames{l} {}
 
    inline void Lexer::Reset(std::queue<WChar> & q)
    {
        expression = &q;
        tableOfSymbols.Clear();
        pastToken = Empty;
    }
 
    inline Lexer::operator bool()
    {
        return expression != nullptr && !expression->empty();            
    }
 
    inline TableOfSymbols<> & Lexer::GetTableOfSymbol()
    {
        return tableOfSymbols;
    }
}
0
261 / 111 / 53
Регистрация: 22.01.2017
Сообщений: 448
05.07.2020, 18:34 33
Цитата Сообщение от Undisputed Посмотреть сообщение
тогда будет срабатывать оператор присваивания копированием (к чему лишние копии?)
Это понятно, move придется реализовать. Я к вопросу об указателе, на сколько он принципиален.

Не по теме:

Сам не люблю контейнер через указатель дергать.

0
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
05.07.2020, 18:55 34
Цитата Сообщение от hoggy Посмотреть сообщение
такое впечатление, что автору кода совершенно пофигу
почему это пофигу? автор смотрит если есть вершина то удаляет ее и выдает репорт

Цитата Сообщение от hoggy Посмотреть сообщение
дело не в том: проще или нет.
ну я именно сейчас говорю про то что так проще и если где-то нам нужно удалять из контейнера и с проверкой перед удалением, то проверку можно организовать по разному и в каком то случае код может быть короче но с сохранением сути - вот что я говорю... и если скажем тебе в 10 местах нужно перед удалением проверить контейнер на пустоту (или типичный find + erase) то упаковка проверки в метод позволит не только сократить код в локальном участке, это так же избавит от необходимости дублировать эти проверки во всех 10 местах...

Цитата Сообщение от hoggy Посмотреть сообщение
все случаи работы с очередями сводились к тому
ок пусть это будет не стек... посмотри std::map::erase (перегрузка которая удаляет элемент по ключу).
она как раз таки возвращает количество удаленных элементов (если 0 - значит ничего не удалили).
вот есть такой вариант удаления элемента по ключу (если он есть)
C++
1
2
3
4
std::map<int,int> m{{1,2},{3,4}};
if (m.erase(3) != 0) {
    std::cout << "erased\n";
}
а есть такой вариант
C++
1
2
3
4
5
auto it = m.find(1);
if (it != m.end()) {
    m.erase(it);
    std::cout << "erased\n";
}
из примера выше следует что такой подход местами используется в том числе и в стандартной библиотеке

то есть в одном случае мы опираясь на возвращаемое значение метода который отвечает за удаление выдаем репорт
а в другом случае мы сначала проверяем есть ли элемент а потом удаляем его и выдаем репорт
суть одна и та же просто первый вариант более краток
причем в случае std::map::erase(key) у нас 2 варианта: возвращаемое значение либо 0 либо 1 (т.к ключи уникальные) что в принципе как раз таки намекает на bool

Добавлено через 3 минуты
Цитата Сообщение от n1b1ru Посмотреть сообщение
move придется реализовать
все равно с move тоже скорее всего будут лишние операции (обычно конструктор перемещения это больше чем копирование значения единственного указателя)
1
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
05.07.2020, 19:04 35
_stanislav, Ну здесь по всей видимости стоит пересмотреть а насколько нужно выдергивать токены по одному. Возможно стоит посмотреть в сторону того, что лексер преобразовывает сразу всю входную строку в строку токенов, потом работает уже с ней. Такая строка токенов и гораздо меньше (ну к примеру для glext.h что то около 75k токенов на мегабайт текста) - т.е. работа с ней будет гораздо быстрее, ну и в результате и с указателем чужим геморроя нет и к кешу более дружелюбно будет однозначно.
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
05.07.2020, 19:09  [ТС] 36
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Ну здесь по всей видимости стоит пересмотреть а насколько нужно выдергивать токены по одному.
спасибо за совет
0
261 / 111 / 53
Регистрация: 22.01.2017
Сообщений: 448
05.07.2020, 19:31 37
Undisputed, на сколько правильна следующая реализация (оставим пока эффективность, ну и move assignment):
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
class SomeClass {
private:
    using Container = std::queue<int>;
    Container p;
 
public:
    SomeClass() {}
    SomeClass(Container & r) : p{r} {}
    SomeClass(Container && r) : p{std::move(r)} {}
    
    void Reset(Container & r) {
        p = r;
    }
 
    void Reset(Container && r) {
        p = std::move(r);
    }
};
 
std::queue<int> getQueue(std::initializer_list<int> lst) {
    std::queue<int> q;
    for(const int& el: lst) {
        q.push(el);
    }
    
    return q;
}
 
int main() {
    SomeClass s(getQueue({ 1, 2, 3, 4, 5 }));
    auto q = getQueue({ 1, 2, 3, 4, 5 });
    s.Reset(q);
    s.Reset(getQueue({ 1, 2, 3, 4, 5 }));
}
0
875 / 461 / 91
Регистрация: 10.06.2014
Сообщений: 2,669
05.07.2020, 19:35 38
n1b1ru,
Я ещё забыл отметить, что в случае с move будет испорчен исходный объект что может быть неприемлемо в конкретной ситуации.

А на сколько правильный код о котором вы спросили уже зависит от конкретной задачи. Это зависит от того что вы пытаетесь получить в конечном счёте.
0
261 / 111 / 53
Регистрация: 22.01.2017
Сообщений: 448
05.07.2020, 19:44 39
Undisputed, задача реализовать композицию.
Цитата Сообщение от Undisputed Посмотреть сообщение
Я ещё забыл отметить, что в случае с move будет испорчен исходный объект что может быть неприемлемо в конкретной ситуации.
В моем случае исходный объект временный.
0
"C with Classes"
1646 / 1403 / 523
Регистрация: 16.08.2014
Сообщений: 5,877
Записей в блоге: 1
05.07.2020, 19:47  [ТС] 40
Цитата Сообщение от n1b1ru Посмотреть сообщение
SomeClass(Container && r)
а тут ты что хотел сказать?
0
05.07.2020, 19:47
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.07.2020, 19:47
Помогаю со студенческими работами здесь

Чем плохой указатель на void?
Здравствуйте! Недавно прочитал статью на хабре http://habrahabr.ru/post/102930/ Сабж - архитектура...

Итератор и указатель в чем разница
Здравствуйте, Подскажите пожалуйста, вот есть такое определение: Для получения итераторов...

Чем можно заменить заменить toggle() ?
Добрый день, у меня такой вопрос. Чем можно заменить toggle(function(), function()); В ранних...

Как заменить переменную i на указатель?
вычисляю факториал числа. нужно заменить переменные на указатели. две переменные заменил, прога...

Строковый литерал и указатель на строку. В чем разница?
Добрый день. Начал только изучать С++, не могу понять в чем разница между указателем на литерал и...

Что такое указатель и с чем его есть
Я уже не знаю что делать, но в книжке очень непонятно написано про указатели. Не могли бы вы...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru