Войти
ФлеймФорумПрограммирование

Деокмпозиция сложных вызовов API с указателями (2 стр)

Страницы: 1 2 3 Следующая »
#15
5:28, 2 мар. 2021

kkolyan
> проблема в том, что тогда вложенные указатели оказываются без присмотра. после
> выхода из "initA" они окажутся либо невалидны, либо увековечены.

Я не понял что тут за проблема.
Если callMe ожидает что вложенные указатели настроены определённым образом, то почему initA не может их настроить должным образом?

#16
(Правка: 5:51) 5:31, 2 мар. 2021

=A=L=X=
> Если callMe ожидает что вложенные указатели настроены определённым образом, то почему initA не может их настроить должным образом?

при данной вами сигнатуре "initA" (хотя я не совсем понял что вы предлагаете вместо трех точек), настроить чтобы они были доступны в callMe - легко. например разместить их контент в куче или в инстансе текущего класса. но в инстансе класса мы не хотим, т.к. не хотим их хранить так долго. а в куче не хотим, т.к. кто же их оттуда удалит.

PS: напомню, что вопрос не в том "как сделать чтобы работало" (ударьте меня по лицу, когда я начну такое спрашивать). я же в нулевом посте описал 4 способа, каждый из которых отлично работает. Вопрос в том - какой из подходов в современном крестопрограммировании более актуален.

#17
(Правка: 11:21) 11:13, 2 мар. 2021

kkolyan
> это вариант 1 - простынка. большая, плохонавигируемая, в которой смешано много
> разного.
Что значит большая простынка? Вот твой велосипед на менеджере ссылок:

void mainMethod()
  Scope scope;

  Params params;

  params.a = &scope.place(createA(scope));
  ... // в таком духе для каждого параметра

  Result result = callMe(params);
}
А вот простынка:
void mainMethod()
  Scope scope;

  Params params;

  A a(params_for_a);
  ... // в таком духе для каждого параметра

  Result result = callMe(Params(a, b... ));
}
Всё что нужно - определить конструктор у params 1 раз:
  struct Params {
    A* a;
    B* b;
    C* c;
    D* d;
    E* e;
    F* f;
    G* g;
    prarms(A& a, B& b....) {
      this->a = &a;
      this->b = &b;
      ... // в таком духе для каждого параметра
    }
  };
#18
16:14, 2 мар. 2021

Кстати, по поводу 2 и 4 вариантов ещё хотелось бы добавить, что new - это дорогая операция. Просто так на ровном месте стековую аллокацию на new лучше не заменять. Поэтому, по-хорошему, выбор идёт между вариантами 1 (c-style) и 3 (oop-style)

#19
17:39, 2 мар. 2021

MrShoor
> Что значит большая простынка

+ Показать

> Вот твой велосипед на менеджере ссылок:
> А вот простынка:

ага, а теперь замени в своем примере "params_for_a" на "структурки с 1-20 полями, некоторые из которых тоже указатели" для честности.

> Всё что нужно - определить конструктор у params 1 раз:
"Допустим, есть некое сторонее API вот с такой сигнатурой:".

#20
17:40, 2 мар. 2021

pahaa
> Кстати, по поводу 2 и 4 вариантов ещё хотелось бы добавить, что new - это дорогая операция. Просто так на ровном месте стековую аллокацию на new лучше не заменять. Поэтому, по-хорошему, выбор идёт между вариантами 1 (c-style) и 3 (oop-style)

эх, ну ладно. значит 3...

#21
(Правка: 18:42) 18:41, 2 мар. 2021

kkolyan
> ага, а теперь замени в своем примере "params_for_a" на "структурки с 1-20
> полями, некоторые из которых тоже указатели" для честности.
Твой пример сильно в вакууме.
Вот как твоё createA(scope) из способа 4 узнает, что ты хотел в a.x записать 12;  а в - a.y записать 17; ? Ты в любом случае где-то передаешь эти 12 и 17.
Но давай простоты ради я упрощу простыню, которую ты написал:

void mainMethod()
  Scope scope;

  A a(12, 17, {42, -7});

  B b(12, 17, {42, -7});

  Result result = callMe(Params(a, b));
}
Теперь всего лишь нужно описать конструкторы и всё.

kkolyan
> "Допустим, есть некое сторонее API вот с такой сигнатурой:".
И? Как это противоречит?
Не можешь добавить констукртор в Params - напиши фукнцию MakeParams которая возвращает Params. Код поменяется на Result result = callMe(MakeParams(a, b));

#22
(Правка: 1:10) 1:09, 3 мар. 2021

MrShoor
> Но давай простоты ради я упрощу простыню, которую ты написал:

ты упростил, изменив A и callMe в удобную сторону (добавив конструктор и заменив указатели на ссылки или значения). если бы так можно было, и вопроса бы не было.
как бы ты упростил такой код, не меняя структуру A и сигнатуру callMe?

MrShoor
> И? Как это противоречит?

API же сторонее - не могу его менять.

MrShoor
> напиши фукнцию MakeParams которая возвращает Params

где будут аллоцироваться значения для вложенных указателей? (например "zs" в моем примере)

MrShoor
> Вот как твоё createA(scope) из способа 4 узнает, что ты хотел в a.x записать 12; а в - a.y записать 17; ? Ты в любом случае где-то передаешь эти 12 и 17.

да, разумеется, будут еще параметры - какие-то другие наши классы. они оформлены удобно - т.е. там и конструкторы хорошие и все такое, но структура данных отличается - просто написать что-то вроде "a.zs = &myParam.zs" не получится (в каких-то случаях конечно получится, но в этом треде они не интересны).

например, A создается на основании вот такой структуры:

struct MyClass {
  MyClass1 field1;
  MyClass2 field2;
  std::vector<MyClass3> field3;
}
а вот дописанный с учетом этого в 4-ый вариант:
A createA(Scope& scope, const MyClass& source) {  
  A a;
  a.x = source.field1.x;
  a.y = source.field2.y;

  std::vector<int>& zs = scope.place(std::vector<int>());
  for (const MyClass3& item: source.field3) {
    zs.emplace_back(item.z);
  }
  a.zCount = zs.size();
  a.zs = zs.data();
  return a;
}

#23
2:54, 3 мар. 2021

kkolyan
> как бы ты упростил такой код, не меняя структуру A и сигнатуру callMe?
Нуу, например так:

+ Показать
#24
7:46, 3 мар. 2021

kkolyan
> a.zs = zs.data();
> return a;
Висящий указатель образуется

#25
(Правка: 9:30) 9:23, 3 мар. 2021

1 frag / 2 deaths
> Висящий указатель образуется
неа) этот вектор прибивается в декструкторе класса Scope (его полный код под катом в нулевом посте).

MrShoor
спасибо за подробный пример! примерно это я имел в виде под вариантом 3. пока что этот вариант явный фаворит)

#26
11:40, 3 мар. 2021

В данном случае, поскольку это Ц++, а не презренный $hарп, начать следует с прояснения момента - кто будет владеть объектами по этим самым указателям, а также вложенным указателям? Вызывающий или вызываемый? Или посредством вызова владение расшаривается?
Ответ на этот вопрос будет содержать 95% ответа о том, как оптимальнее организовать эту пачку структур.

#27
11:45, 3 мар. 2021

Sbtrn. Devil
> кто будет владеть объектами по этим самым указателям, а также вложенным указателям?

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

#28
13:26, 3 мар. 2021

Я за простейшее решение с объектами на стеке.

#29
14:58, 3 мар. 2021

kkolyan
Ну тогда и смартпоинтер (auto_ptr) под A-G сгодится. Передавать в функцию обычным указателем, извлекаемым через get(), а менеджмент массивов по вложенным указателям делать ручками на вызывающей стороне, как всё равно бы пришлось.
Это если нельзя, как предлагают тут, просто на стеке разместить.

Страницы: 1 2 3 Следующая »
ФлеймФорумПрограммирование