eXmire
> Какое отношение указатели имеют к ссылкам?
Я уже запутался. Ты про какие ссылки вообще говоришь?
Не про &
> Слишком узко мыслишь. Речь не про так называемые "ссылки" языка C++.
Не про *
> Мне снова-таки непонятно, каким местом здесь указатели всплыли, если речь была
> про ссылки?
-Eugene-
> Я уже запутался. Ты про какие ссылки вообще говоришь?
Ссылка:
- внешне полностью повторяет value, но любое изменение данных по ссылке отражается на объекте, находившемуся по правую сторону знака "равно" при присваивании/инициализации
- если ссылка указывает на объект, значит объект обязан существовать. иными словами, время жизни объекта определяется временем жизни всех ссылок на него
Речь про концепт. Конкретная реализация не имеет значения. Ну и само собой, ссылки должны быть переприсваиваемыми, а не константными, как в C++.
eXmire
- Скажите, а правда, что Абрамович выиграл в лотерею миллион?
- Правда, только не Абрамович, а Рабинович, не в лотерею, а в карты, не миллион, а сто рублей и не выиграл, а проиграл.
говорите, умные указатели, надо везде и всюду использовать?
ага:
#include <glfw3.h> std::shared_ptr<GLFWwindow> m_window = std::make_shared<GLFWwindow>(glfwCreateWindow( width, height, title.c_str( ), nullptr, nullptr));
Ну и сиди, думай о бытии этого мира.....
Бажа в том что в GLFW не дают сам объект. только его объявление:
glfw3.h:
typedef struct GLFWwindow GLFWwindow;
А умному указателю капец как надо оператор копирования
Хотя в данном случае именно тут он и нужен был, потому что GLFWwindow потом по движку расходится в разные направления со всеми вытекающими
Может это решаемо? (нет, так нет, не хочу заморачиваться - все равно еще перепишется)
p.s. да, у меня русская студия и мне глубоко фиолетово. я не фанатик (а если нужно уточнение, ошибки ищу по кодам типа error C2079)
war_zes
Скорее всего из-за того, что glfwCreateWindow() выделяет память используя calloc(). std::shared_ptr освобождает память использую delete, а не free(). Это две разные системы распределения памяти их смешивать нельзя.
Funtik
Можно добавить glfwDestroyWindow как свой deleter, не сложнее лямбды.
war_zes
Там везде указатели используются, потому особо никто не запаривается с определением структур. С-стиль, что поделать, он всегда плохо уживался с плюсами. Создайте свой класс с обёрткой указателя, перегрузите оператор разыменования и взятия адреса, и будет вам пол-счастья
class Int { int * i; public: Int(int j = 0):i( new int( j)){} int* pointer( ){return i;} int& value( ){return *i;} ~Int( ){delete i; i = nullptr;} }; int& operator*( shared_ptr<Int>& i) { return i->value( ); } int* operator&( shared_ptr<Int>& i) { return i->pointer( ); } int main( ) { shared_ptr<Int> k( new Int( 16)); *k = 64; return *k; }
war_zes
> говорите, умные указатели, надо везде и всюду использовать?
Нет, нужно думать головой.
Если мы видим вот такой код:
typedef struct GLFWwindow GLFWwindow;
Значит имеем дело с интерфейсной частью библиотеки, написанной на Си. И как уже отметили выше, пихать такие вещи в shared_ptr нельзя (хотя это вроде очевидно должно быть Оо).
war_zes
> Бажа в том что в GLFW не дают сам объект. только его объявление
В том месте нет никакого объявления объекта, это нужно лишь для определения своего типа указателя (GLFWwindow *), и следовательно какой-то мало мальской "type safety".
В данном случае мы имеем хендлы. И shared_ptr к ним неприменим, ни с кастомными дэлитерами, ни без. Он чисто логически к ним не применяется.
eXmire
> . И shared_ptr к ним неприменим, ни с кастомными дэлитерами, ни без. Он чисто
> логически к ним не применяется
Почему это? Он применим к любой сущности, которую можно создать и удалить, зато нежелательно или невозможно копировать.
eXmire
> В данном случае мы имеем хендлы. И shared_ptr к ним неприменим, ни с кастомными
> дэлитерами, ни без. Он чисто логически к ним не применяется.
все там прекрасно применяется.
и технически, и логически.
war_zes
> Может это решаемо
да.
сначала рассмотрим вашу ошибку:
std::shared_ptr<GLFWwindow> m_window = std::make_shared<GLFWwindow>(glfwCreateWindow( width, height, title.c_str( ), nullptr, nullptr));
упрощаю запись:
// указатель на построенный объект GLFWwindow* ptr = glfwCreateWindow(width, height, title.c_str( ), nullptr, nullptr); std::make_shared<GLFWwindow>( ptr); // <—- WTF???
ваша ошибка в недопонимании принципа работы фабрики смарт-поинтеров.
как работает std::make_shared?
он пинает конструктор объекта, дергая конструктор с указанными аргументами
то есть, вы попытались построить объект неполного типа,
передав в качестве аргумента указатель на другой объект,
который был построен с помощью апи-функции.
как вы видите, кейс вообще не правильный,
вам здесь std::make_shared вообще не нужен.
у вас уже есть апи-функция,
которая умеет строить нужные вам объекты.
вам нужно просто запихнуть этот указатель в шаред,
и указать апи-функцию удаления.
концептуальный пример:
#include <iostream> #include <memory> typedef struct GLFWwindow GLFWwindow; struct GLFWmonitor{}; // допустим это наша апи-функция для создания сишных объектов GLFWwindow* glfwCreateWindow(int width, int height, const char *title, GLFWmonitor *monitor, GLFWwindow *share) { static int hack = 10; std::cout << "window: " << hack << " was created\n"; return ( GLFWwindow*)&hack; } // соотвественно, должна быть функция удаления этих объектов void glfwDestroyWindow( GLFWwindow *window) { int* hack = ( int*)window; std::cout << "window: " << *hack << " was destroyed\n"; } int main( ) { std::cout << "Hello, world!\n"; // для создания объекта используем специально предназначенное для этого апи auto* ptr = glfwCreateWindow( 800, 600, "ololo", nullptr, nullptr); // далее создаем шаред_птр, указав ресурс, и апи-функцию удаления std::shared_ptr<GLFWwindow> window( ptr, glfwDestroyWindow); }
ну и так, для ознакомления:
смарт-поинтеры - это больше чем просто способ контроля за утечками памяти.
это - мощный паттерн,
позволяющий детально контролировать время жизни и права доступа ресурсов.
(с)
http://www.cyberforum.ru/cpp-beginners/thread1500101.html#post7882976
Kartonagnick
> все там прекрасно применяется.
> и технически, и логически.
Про "технически" никто ничего не говорил. Насчет логически:
В документации GLFW четко сказано, что GLFWwindow* - это хендл. А значит, логически, это никакой не "указатель на объект", а некий идентификатор. Хедл в качестве инвалидного значения может иметь NULL, а может и любой другой INVALID_HANDLE.
Это может быть вообще не указатель, а просто индекс.
А теперь ответь мне на такой вопрос: какой смысл приобретает операция разыменовывания в случае shared_ptr<GLFWwindow>?.
eXmire
> В документации GLFW четко сказано, что GLFWwindow* - это хендл.
в документации указан прототип:
GLFWwindow* glfwCreateWindow(int width, int height, const char *title, GLFWmonitor *monitor, GLFWwindow *share)
и это все, что нужно знать, что бы работать.
eXmire
> А значит, логически, это никакой не "указатель на объект", а некий
> идентификатор.
да хоть писькой назовите.
для шаред_птр это - монопенисуальный фактор.
eXmire
> Это может быть вообще не указатель, а просто индекс.
не может.
безотносительно к тому,
как там все устроенно внутри самого апи.
функция возвращает именно указатель.
это - синтаксис языка.
я поясню мысль:
handle foo(); // <—- вот это хэндл. // по факту это может быть указателем, либо чем то ещё // в будущей реализации они могут запросто поменять тайпдеф. // для клиентов это будет прозрачно, // если они не будут закладываться на то, // что именно там тайпдеффицо
handle* foo(); // <—- а вот это - указатель. // безотносительно к тому, что чем на самом деле является сам handle, // функция возвращает указатель // и клиенты вправе на это закладываццо
eXmire
> какой смысл приобретает операция разыменовывания в случае
> shared_ptr<GLFWwindow>?
абсолютно все тоже самое, что и обычно - референс на ресурс.
Это всё из-за спайса табов.
Тема в архиве.