К какому использование - несколько косвенность в C++?

Тестирование с помощью https://matplotlib.org/examples/animation/dynamic_image.html Я просто добавляю

%matplotlib notebook

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

10
задан LogicStuff 22 December 2015 в 23:02
поделиться

8 ответов

Наиболее распространенное использование как @aku указанный должно позволить изменению в параметре указателя быть видимым после функциональных возвратов.

#include <iostream>

using namespace std;

struct Foo {
    int a;
};

void CreateFoo(Foo** p) {
    *p = new Foo();
    (*p)->a = 12;
}

int main(int argc, char* argv[])
{
    Foo* p = NULL;
    CreateFoo(&p);
    cout << p->a << endl;
    delete p;
    return 0;
}

Это распечатает

12

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

#include <iostream>

using namespace std;

int main(int argc, char* argv[])
{
    const char* words[] = { "first", "second", NULL };
    for (const char** p = words; *p != NULL; ++p) {
        cout << *p << endl;
    }

    return 0;
}
12
ответ дан 3 December 2019 в 14:54
поделиться

IMO наиболее распространенное использование должен передать ссылку на переменную указателя

void test(int ** var)
{
 ...
}

int *foo = ...
test(&foo);

Можно создать многомерный зубчатый массив с помощью двойных указателей:

int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
7
ответ дан 3 December 2019 в 14:54
поделиться

Один общий сценарий - то, куда необходимо передать нулевого указателя функции, и инициализировать его в той функции, и используемый вне функции. Без multplie косвенности функция вызова никогда не имела бы доступа к инициализированному объекту.

Рассмотрите следующую функцию:

initialize(foo* my_foo)
{
    my_foo = new Foo();
}

Любая функция, которая звонит, 'инициализирует (нечто*)' не будет иметь доступа к инициализированному экземпляру Foo, потому что указатель, это передается этой функции, является копией. (Указатель является просто целым числом, в конце концов, и целые числа передаются значением.)

Однако, если функция была определена как это:

initialize(foo** my_foo)
{
    *my_foo = new Foo();
}

... и это назвали как это...

Foo* my_foo;

initialize(&my_foo);

... затем у вызывающей стороны был бы доступ к инициализированному экземпляру через 'my_foo' - потому что это - адрес указателя, который был передан для 'инициализирования'.

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

5
ответ дан 3 December 2019 в 14:54
поделиться

При передаче указателя в как выходной параметр Вы могли бы хотеть передать его как Foo** и установленный его значение как *ppFoo = pSomeOtherFoo.

И от algorithms-and-data-structures отдела, можно использовать ту двойную косвенность для обновления указателей, которые могут быть быстрее, чем, например, свопинг фактических объектов.

3
ответ дан 3 December 2019 в 14:54
поделиться

Carl: Ваш пример должен быть:

*p = x;

(У Вас есть две звезды.) :-)

1
ответ дан 3 December 2019 в 14:54
поделиться

Простой пример использовал бы int** foo_mat как 2-й массив целых чисел. Или можно также использовать указатели на указатели - позволяет, говорят, что у Вас есть указатель void* foo и у Вас есть 2 различных объекта, которые имеют ссылку на него со следующими членами: void** foo_pointer1 и void** foo_pointer2, при наличии указателя на указатель можно на самом деле проверить ли *foo_pointer1 == NULL который указывает, что нечто является ПУСТЫМ. Вы не смогли бы проверить, является ли нечто ПУСТЫМ, если foo_pointer1 был регулярным указателем. Я надеюсь, что мое объяснение не было слишком грязно :)

1
ответ дан 3 December 2019 в 14:54
поделиться

В C абсолютно требуется идиома. Рассмотрите проблему, в которой Вы хотите, чтобы функция добавила строку (чистый C, таким образом, символ *) к массиву указателей для обугливания *. Прототип функции требует трех уровней абстракции:

int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);

Мы называем его следующим образом:

unsigned int   the_count = 0;
char         **the_list  = NULL;

AddStringToList(&the_count, &the_list, "The string I'm adding");

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

int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
1
ответ дан 3 December 2019 в 14:54
поделиться

Обычно, когда Вы передаете указатель на функцию как возвращаемое значение:

ErrorCode AllocateObject (void **object);

куда функция возвращает код ошибки успеха/отказа и заполняет параметр объекта с указателем на новый объект:

*object = new Object;

Это используется много в COM, программирующем в Win32.

Это - больше вещи C сделать, в C++ можно часто переносить этот тип системы в класс для создания кода более читаемым.

1
ответ дан 3 December 2019 в 14:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: