LINUX.ORG.RU

std::variant и двойной вызов деструктора

 , ,


0

2
#include <iostream>
#include <variant>
using namespace std;

template<int nd>
class base {};

template<int nd>
class base_holder : public base<nd>{
public:
	 base_holder () {
		cout<<"new base_holder<"<<nd<<"> = "<<this<<endl;
	}
	~base_holder () {
		cout<<"del base_holder<"<<nd<<"> = "<<this<<endl;
	}
};

std::variant<base_holder<1>, base_holder<2>, base_holder<3>>
new_base_holder(int nd) {
	switch (nd) {
		case  1: return base_holder<1>();
		case  2: return base_holder<2>();
		case  3: return base_holder<3>();
		default: throw "";
	}
}

int main(int argc, char **argv){

	auto cc = new_base_holder(2);
	cout<<"tt"<<endl;
	
	return 0;
}

А на выходе:

new base_holder<2> = 0x7ffe8b143a77
del base_holder<2> = 0x7ffe8b143a77
tt
del base_holder<2> = 0x7ffe8b143aa6
Собственно, почему так происходит и ЧЯДНТ?

★★★★★

Последнее исправление: thunar (всего исправлений: 1)
Ответ на: комментарий от thunar

А как по-твоему variant засовывает в себя объект который ты ему передаёшь?

anonymous
()
Ответ на: комментарий от slovazap

Ага, вижу, он move constructor использует.

thunar ★★★★★
() автор топика

Всё, разобрался, унаследовал base_holder от std::variant и инициализировал его в конструкторе через emplace.

thunar ★★★★★
() автор топика
Ответ на: комментарий от thunar

Не надо этого делать. Попробуй return std::variant{base_holder<1>()}. Похоже, что у тебя либо rvo не включился - это с++98 вообще, либо где-то elision не сделался - это с++17, но вообще даже гцц 5 по-моему умеет это делать без с++17. Ты точно с включенными оптимизациями компилируешь или с О0?

anonymous
()
Ответ на: комментарий от const86

Ну мне такая семантика в принципе и нужна была. Полиморфный класс который определяется параметрами конструктора.

thunar ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Что поможет от копирования это опереться на NRVO. Создоём std::variant<...> ret; и делаем ret.emplace<base_holder<n>>();.

anonymous
()

Отличный тред! Люблю такое!

Ты ещё молодец что заметил, обычно такое на продакшне живёт год до взрыва

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от thunar

Всё, разобрался, унаследовал base_holder от std::variant и инициализировал его в конструкторе через emplace.

Наследование от std::variant может работать не так как ты ожидаешь с std::visit.

Вчера как раз голосование было, и вот какие правки вошли в С++23: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2162r2.html

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от anonymous

получается так как запрограммирует программист, вот так с++ и работает, а не как в джаве.

anonymous
()
Ответ на: комментарий от anonymous

Скакание по граблям с треском лопающихся яиц - отличное время провождение для каждого С++ программиста. Вместо того чтобы писать осмысленный код

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

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

anonymous
()
Ответ на: удаленный комментарий

Для обьекта который програмист не делал для копирования, а он скопировался вполне вылезет какой-то double free и будете потом дебажить

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от anonymous

А программист взял и не удалил. Потому что С++ позволяет делать такие детские ошибки своим тупейшим дефолтным поведением. И они еще в ряде юнит-тестов на деле не вылезают, даже под санитайзером. Все отлично собралось, без ворнингов и тесты прошло

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 2)
Ответ на: комментарий от vertexua

А программист взял и не удалил.

Проблема уровня «а программист взял и запушил не в ту ветку».

Какой язык от этого защитит?

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от fsb4000

Вчера как раз голосование было

Ох, так ты LWG-шник. Почему многие LWG-шники нифига не знают C++?

anonymous
()
Ответ на: комментарий от anonymous

Я понимаю этот аргумент и полностью с ним согласен.

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

Когда делали С++ - просто не предусмотрели. Сейчас уже поздно, потому что много кода должно компилироваться. Претензии к создателям С++ ровно ноль, это все нормальный процесс.

Претензия к пользователям С++, которым в лицо божья роса и вот С++ нам прямо идеальная манна небесная, больше ни о чем мечтать нельзя. Ну это же совсем неадекватный подход.

В моем понимании (и кстати в моем окружении FAANG так и происходит) С++ разработчики должны первыми радоваться появлению языков вроде Rust, которые построены по тем же принципам, но с учетом полученого опыта. Им не нужно переучиваться, они просто получают мягкие, покрытые лаком ручки там где раньше кололось. Он уже и так в принципе давно пишут в этом стиле, но время от времени неприятные ошибки всплывают потому что мы все люди, а не машины. Если можем сделать ошибку, то в одном из десяти случаев мы ее сделаем

vertexua ★★★★★
()

Забейте на кресты.

Всем Chez Scheme, посоны.

anonymous
()
Ответ на: комментарий от vertexua

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

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

anonymous
()
Ответ на: комментарий от vertexua

В этом коде единственная ошибка автора в том, что он не переопределил конструктор. А вот, перемещения или копирования - еще вопрос. Так-то формально копирование, но благодаря одному из десятка случаев copy elision, скорее всего, копирование не будет использовано, а современный компилятор C++ сразу вфигачит перемещение.

По сравнению с rust это, конечно, все бесит. В rust не задумываешься о таких ненужных вещах - там все работает кристально чисто. А вот в C++ нужно набить руку, и глаз должен пристреляться, чтобы на автомате такие вещи определять. Ну, не понимаю тех, кто считает, что rust сложнее, чем C++. По-моему, ровно наоборот: C++ гораздо сложнее, чем rust. Это видно даже на таком простейшем примере.

С этим variant другая проблема - он медленный и неэффективный по сравнения с enum из rust. Увы, если в rust можно считать, что обычное сопоставление с образцом работает быстро, компилятор rust создает эффективный код, на который можно положиться, то в случае C++ в критических по эффективности местах кода variant лучше не использовать. Лучше самому расписать все через union аккуратно. Вот так вот. Это проблема. Zero cost наизнанку, короче)

anonymous
()
Ответ на: комментарий от anonymous

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

ну в расте в принципе нет возможности создать объект «на месте», все что там можно сделать - это скопировать его откуда-то еще (хорошо если без .clone()).

На этом фоне претензии к C++ смотрятся, мягко говоря, лицемерно.

Lrrr ★★★★★
()
Ответ на: комментарий от Lrrr

Вообще не в тему!

Тут человек открыл для себя, что для «перемещенного» объекта вызывается деструктор, а ты кричишь о каком-то «лицемерии»

anonymous
()
Ответ на: комментарий от us976

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

anonymous
()
Ответ на: комментарий от anonymous

Нет, ты ошибаешься основной вопрос, почему ты пересказываешь непроверенные факты, которые тебе плюсовые пропагандисты сообщили. В расте можно создавать «объекты» на месте и об этом пишут на первых страницах.

Пример:

vec![1, 2, 4]
us976
()
Ответ на: комментарий от us976

этот макрос принимает на вход уже готовые объекты, а не создает их из аргументов. Твой пример некорректен (мягко говоря). Хочешь привести корректный - напиши аналог плюсового vector::emplace_back(). Ну или, если говорить об этой теме,

using var_t = std::variant<base_holder<1>, base_holder<2>, base_holder<3>>;
...
return var_t{std::in_place_type_t<base_holder<1>>{}};
Lrrr ★★★★★
()
Ответ на: комментарий от us976

В расте можно создавать «объекты» на месте и об этом пишут на первых страницах.

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

vec1, 2, 4

И ты тут же перданул в лужу. Потому как говномакросы не являются частью языка и любое их появление у тебя равнозначну «нет».

Тебе нужно показать emplace, но ты его никогда не покажешь. А то что ты показал - ты лишь ещё больше себя закопал, потому как это именно копирование объектов через создание массива.

$crate::vec::from_elem($elem, $n) где T == T: Clone

anonymous
()
Ответ на: комментарий от anonymous

Потому как говномакросы не являются частью языка

В с/с++ может и не являются, но в ruste это часть языка. macro_rules основной макрос с помощью которого объявляют другие макросы, тот же vec является частью alloc crate.

именно копирование объектов через создание массива

Чего??

#[derive(Debug)]
struct S(i32);

let v = vec!(S(5), S(8));

и где тут копирование?

anonymous
()
Ответ на: комментарий от anonymous

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

По поводу блеяния. Emplace родил, бегом. Объяснять в очередной раз очередному идиоту мне лень. Обгадишься и осознаешь.

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

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

Очередная жертва пропаганды. Может ещё линкер не является частью языка?

anonymous
()
Ответ на: комментарий от anonymous

Какая тупая обезьяна. Блеет рандомную херню, вместо ответов. При этом даже здесь обезьяна обделалась, потому как у говнораста нету линкера. Есть ворованный сишный линкер из llvm. Ты хочешь сообщить, что этот ворованный линкер является частью языка? У тебя там как с методичкой?

О копирование я ничего более не услышу, я правильно понял, отребье?

anonymous
()
Ответ на: комментарий от anonymous

Галоперидолу попей

Да я вообще не растосектант и не про какие inplace писать не собирался. Просто решил порофлить с шизика с маня-определениями что есть часть языка, а что не есть часть языка.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.