Форум программистов, компьютерный форум, киберфорум С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
 Аватар для zayats80888
6343 / 3514 / 1427
Регистрация: 07.02.2019
Сообщений: 8,979
1

UB or not UB?

02.07.2019, 13:50. Показов 1225. Ответов 12
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здрасти, собственно вопрос в теме. По невнимательности забиндил не тот метод, но код скомпилировался и нормально работал работал, случайно заметил. Во внутренности functional не вникал пока, поясните по возможности, как так то, ё маё?

Ситуация примерно такая:
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
#include <functional>
 
using std::placeholders::_1;
using std::placeholders::_2;
 
class B
{
public:
    using Callback = std::function<void(int, int)>;
 
    B(Callback cb) : m_cb{ std::move(cb) } {}
 
    void call()
    {
        if (m_cb) m_cb(a, b);
    }
private:
    int a{ 3 },
        b{ 5 };
    Callback m_cb{ nullptr };
};
 
class C
{
public:
    C() : obj{ std::bind(&C::wrong, this) } {} // забиндил не тот метод
 
    void wrong() {}
 
    void run() { obj.call(); }
private:
    B obj;
};
 
int main()
{
    C c;
    c.run(); // <-- UB?
}
0
Лучшие ответы (1)
900 / 477 / 93
Регистрация: 10.06.2014
Сообщений: 2,698
02.07.2019, 13:57 2
zayats80888,
Вроде все нормально. Почему вы решили что UB?

Добавлено через 1 минуту
И зачем по дефолту Callback nullptr в B?
У вас же всего один способ конструкции экземпляра B, а он уже подразумевает запись в поле с колбеком
0
 Аватар для zayats80888
6343 / 3514 / 1427
Регистрация: 07.02.2019
Сообщений: 8,979
02.07.2019, 14:00  [ТС] 3
Цитата Сообщение от Undisputed Посмотреть сообщение
Почему вы решили что UB?
Я не решил, вот и спрашиваю. У меня же там вызов с параметрами, а они не требуются для этого метода. Куда они помещаются? Да и какой объект получился на выходе bind, что им нормально инициализировался m_cb?

Добавлено через 1 минуту
Цитата Сообщение от Undisputed Посмотреть сообщение
И зачем по дефолту Callback nullptr в B?
Привычка, это просто пример, так то там и default конструктор должен быть
0
 Аватар для eva2326
1660 / 489 / 106
Регистрация: 17.05.2015
Сообщений: 1,500
02.07.2019, 14:02 4
Цитата Сообщение от zayats80888 Посмотреть сообщение
как так то, ё маё?
std::function - тонкая обертка над функторами-реализациями,
которые непосредственно занимаются запуском функций/методов.

В Вашем случае, такой функтор-реализация инстанцируется в строке:
std::bind(&C::wrong, this)

В действительности, вы можете запустить функтор и без std::function:

C++ Скопировано
1
2
auto func = std::bind(&C::wrong, this);
func();
Шаблон функции std::bind знает с какими аргументами его запустили.
Зная типы аргументов, шаблон знает чем и как нужно параметризовать шаблон функтора-реализации.

Таким образом, результат работы std::bind(&C::wrong, this) - это корректный функтор,
заточенный под запуски именно вашей функци-члена &C::wrong,
именно под её количество аргументов.

В этот момент абсолютно не важно,
чем был параметризован std::function
Функтор-реализация заточен для работы с &C::wrong,
а не с std::function

Вот здесь:
Цитата Сообщение от zayats80888 Посмотреть сообщение
void run() { obj.call(); }
Вы запускаете std::function без аргументов.
Соответственно, он делегирует запуск функтору-реализации,
и тоже - без аргументов.

Соответственно, успешно запускается функция-член,
потому что она как раз оказалась без аргументов.

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

C++ Скопировано
1
void run() { obj.call(2,2); }
error: no matching function for call to ‘B::call(int, int)’
Итого: нет, это не UB.
1
 Аватар для zayats80888
6343 / 3514 / 1427
Регистрация: 07.02.2019
Сообщений: 8,979
02.07.2019, 14:21  [ТС] 5
Цитата Сообщение от eva2326 Посмотреть сообщение
Вы запускаете std::function без аргументов.
как же без аргументов, когда if (m_cb) m_cb(a, b);?

Добавлено через 15 минут
eva2326, там должно было быть так:
C++ Скопировано
1
2
3
4
5
6
7
class C
{
public:
    C() : obj{ std::bind(&C::right, this, _1, _2) } {}
 
    void right(int a, int b) { /*...*/ };
    //...
и больше никаких отличий
0
6770 / 4564 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
02.07.2019, 14:38 6
Цитата Сообщение от zayats80888 Посмотреть сообщение
как же без аргументов, когда if (m_cb) m_cb(a, b);?
Если у std::bind нет плейсхолдеров, то он передаёт параметры своего оператора () после сохранённых
2
зомбяк
 Аватар для TRam_
1584 / 1218 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
02.07.2019, 14:41 7
Цитата Сообщение от zayats80888 Посмотреть сообщение
там должно было быть так
В данном случае в
C++ Скопировано
1
m_cb{ std::move(cb) }
произошло преобразование из std::function<void()> в std::function<void(int, int)> . Почему оно было допустимым, не понятно.
0
 Аватар для zayats80888
6343 / 3514 / 1427
Регистрация: 07.02.2019
Сообщений: 8,979
02.07.2019, 14:44  [ТС] 8
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
после сохранённых
Иначе говоря он их просто игнорирует? Но они в действительности куда то же записываются(регистры, стек...), Ничего там важного не потрется? (извиняюсь за глупый вопрос )
0
зомбяк
 Аватар для TRam_
1584 / 1218 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
02.07.2019, 14:48 9
zayats80888, он не игнорирует, он смотрит на объявление void right(int a, int b), а не на число указанных плейсхолдеров. Задашь там void right() и всё сломается.
0
 Аватар для zayats80888
6343 / 3514 / 1427
Регистрация: 07.02.2019
Сообщений: 8,979
02.07.2019, 14:53  [ТС] 10
Цитата Сообщение от TRam_ Посмотреть сообщение
он не игнорирует,
да я про вызов m_cb(a, b) к которому забиндил void wrong()
0
6770 / 4564 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
02.07.2019, 15:02 11
Цитата Сообщение от zayats80888 Посмотреть сообщение
да я про вызов m_cb(a, b) к которому забиндил void wrong()
Нет не игнорирует. Здесь будет что-то типа std::invoke(C::right, this /*это параметры сохранённые в bind*/, a, b /*это параметры вызывающей функции*/).
Игнорирует, когда есть плейсхолдеры.
Хотя, что-то я загнал не то
0
 Аватар для eva2326
1660 / 489 / 106
Регистрация: 17.05.2015
Сообщений: 1,500
02.07.2019, 15:05 12
Лучший ответ Сообщение было отмечено zayats80888 как решение

Решение

Цитата Сообщение от zayats80888 Посмотреть сообщение
как же без аргументов, когда if (m_cb) m_cb(a, b);?
Рассмотрим код:

C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <functional>
#include <iostream>
 
void wrong() 
{
    std::cout << "wrong\n";
}
 
int main()
{
    auto func = std::bind(wrong);
    func(3,4);  // successful call. 
      // unused arguments are evaluated and discarded.
}
Лишние аргументы были проигнорированы.

Здесь нет ни UB, ни ошибки.
Такое поведение - стандартно.

If some of the arguments that are supplied in the call to g() are not matched by any placeholders stored in g, the unused arguments are evaluated and discarded.
https://ru.cppreference.com/w/... ional/bind
1
 Аватар для zayats80888
6343 / 3514 / 1427
Регистрация: 07.02.2019
Сообщений: 8,979
02.07.2019, 15:12  [ТС] 13
eva2326, спасибо. Только тот факт, что std::function проглотил то, что я не планировал, меня озадачил
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Ответ Создать тему

Редактор формул (кликните на картинку в правом углу, чтобы закрыть)
Новые блоги и статьи
Лучшие практики оптимизации Docker Image
Mr. Docker 13.03.2025
Размер Docker-образа влияет на множество аспектов работы с контейнерами. Чем больше образ, тем дольше его загрузка в реестр и выгрузка из него. Для команд разработки, работающих с CI/ CD пайплайнами,. . .
Вопросы на собеседовании по Docker
Mr. Docker 13.03.2025
Ты сидишь напротив технического специалиста, и вдруг звучит вопрос про Docker Swarm или многоэтапные сборки. Пот на лбу? Не переживай, после этой статьи ты будешь готов ко всему! Эта статья будет. . .
Поиск текста в сносках : замена дефиса на тире или тире на дефис...
РоΜа 13.03.2025
Нужно было найти текст в сносках и заменить. Почему-то метод селекшн не сработал. . . пришлось гуглить. найденный на форумвба код пришлось править. Смысл - заменяет в сносках дефисы и тире на нужные. . . .
Real PATH definitions in bash scripts
jigi33 13.03.2025
Как поймать путь и путь к директории относительно запускаемого файла в BASH 1. поймать путь через вывод $(pwd) 2. более правильно - на основе realpath (см. скриншот)
Django или Flask: что выбрать для веб-разработки на Python
py-thonny 13.03.2025
Django – это высокоуровневый фреймворк, который придерживается философии "всё включено". Он предоставляет разработчику готовые решения для большинства типичных задач веб-разработки: от аутентификации. . .
Непрерывное развертывание в Java с Kubernetes
Javaican 13.03.2025
Чем так привлекателен Kubernetes для развертывания Java-приложений? Этот оркестратор контейнеров позволяет автоматизировать развертывание, масштабирование и управление контейнеризированными. . .
Предотвращение XSS, CSRF и SQL-инъекций в JavaScript
run.dev 13.03.2025
JavaScript занимает первые позиции среди языков веб-разработки, но его распространенность делает его привлекательной целью для злоумышленников. Межсайтовый скриптинг (XSS), межсайтовая подделка. . .
PHP 8: JIT-компиляция и улучшение производительно­сти
Jason-Webb 13.03.2025
PHP никогда не славился своей скоростью. Многие сталкивались с проблемами производительности при работе со сложными вычислениями или обработкой больших объемов данных. Традиционная модель выполнения. . .
Сериализация данных с Apache Avro в Kafka
Javaican 12.03.2025
Apache Kafka стала одним из ключевых решений для работы с большими потоками данных. Однако с ростом объемов передаваемых данных возникает проблема: как эффективно сериализовать и десериализовать. . .
Создание потребителей Kafka с помощью Reactor Kafka
Javaican 12.03.2025
Reactor Kafka — это библиотека, объединяющая Apache Kafka с реактивным программированием на базе Project Reactor. Такое сочетание позволяет строить неблокирующие, асинхронные приложения с контролем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
Выделить код Копировать код Сохранить код Нормальный размер Увеличенный размер