C ++: передать общий ptr по ссылке, не нарушая общий доступ? - PullRequest
0 голосов
/ 19 июня 2020

Предположим, я использую умные указатели? Хорошо, отлично:

shared_ptr<whatever>(new whatever());

Мгновенно, я хочу сделать следующее, а не путаться с политикой однократного возврата C ++ и семантами c беспорядка в ней:

void do_something(whatever *& A, whatever *& B){
  auto Aptr = shared_ptr<whatever>(new whatever());
  A = Aptr.get();

  auto Bptr = shared_ptr<whatever>(new whatever());
  B = Bptr.get();
}

Однако , механизм shared_ptr c удаляет объекты по мере их передачи из функции по ссылке, так что пока указатели в моем вызывающем коде

whatever *A,*B;
do_something(A,B);

устанавливаются на соответствующий адрес по ссылке, данные были стерты.


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

Доступ к значениям, инициализированным по ссылке, в целом является желательным механизмом c.


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

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

Вместо этого у меня есть 2 строки для каждого указателя: объявление, функция, которая конструирует их внутренности, и общий ptr, который владеет ими * после вызова функции. Еще одна версия mallo c -free Mechani c.

В идеале, есть способ отбросить эту вторую строку, в которой я владею ptr с общим указателем, или (если это невозможно) способ инициализировать общий указатель внутри функции после объявления указатель общий снаружи. Обратите внимание, что цель здесь:

void func(double * a, int * b, T * c);

double *a; 
int *b; 
T *c;
func(a,b,c); 
// no headaches whatsoever at this scope.

// versus

double *a; 
int *b; 
T *c;
func(a,b,c);
shared_ptr<double> asp(a);
shared_ptr<int> bsp(b);
shared_ptr<T> csp(c,[](T*_){/*special T deletion process*/;};

// versus

double *a; 
int *b; 
T *c;
func(a,b,c);

/* solve the universe */

free(a);
free(b);
delete(T);

Ответы [ 3 ]

2 голосов
/ 19 июня 2020

Может быть, ваша проблема может быть решена структурой с конструктором или двумя:

struct NoNeadachesWhatsoever {
    shared_ptr<double> asp;
    shared_ptr<int> bsp;
    shared_ptr<T> csp;

    NoNeadachesWhatsoever() {
        // initialize members.
    }
};

// ...

NoNeadachesWhatsoever no_headaches_whatsoever;
1 голос
/ 19 июня 2020

Просто используйте общие указатели везде одинаково:

void do_something(std::shared_ptr<whatever> &A, std::shared_ptr<whatever> &B) {
           :
0 голосов
/ 19 июня 2020

У меня плохой ответ, но он сделает то, что вы хотите.

void do_something( whatever *& A, whatever *& B ) {
    static std::shared_ptr<whatever> ptr_a;
    static std::shared_ptr<whatever> ptr_b;
    ptr_a.reset( new whatever );
    ptr_b.reset( new whatever );
    A = ptr_a.get();
    B = ptr_b.get();
}

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

Я думал, что напишу это, даже если это плохой ответ.

Другой ответ, который не так уж плох, будет иметь такой класс:

class Shallocator
{
public:
    Shallocator( whatever *& A, whatever *& B ) {
        ptr_a.reset( new whatever );
        ptr_b.reset( new whatever );
        A = ptr_a.get();
        B = ptr_b.get();
    }
private:
    std::shared_ptr<whatever> ptr_a;
    std::shared_ptr<whatever> ptr_b;
};

тогда в функции вы go:

whatever * A, * B;
Shallocator { A, B };

// no headaches

Память будет освобождена, когда закончится время жизни Shallocator.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...