Почему назначение указателя для объекта Dynami c и массива работает? - PullRequest
0 голосов
/ 31 марта 2020

Ну, во-первых, я хочу знать, является ли следующее «законным» или, по крайней мере, «не злым».

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

Пример:

#include <iostream>
#include <cstring>

int main()
{
    size_t size;
    std::cout << "Enter a size for an array: ";
    std::cin >> size;

    /*Creating a pointer to a single dynamic string*/
    std::string *pointer = new std::string();

    pointer->append("Some text");

    std::cout << pointer << std::endl;

    delete pointer;
    pointer = NULL;

    /*setting it to be an array*/
    pointer = new std::string[size];
    for (size_t i = 0; i < size; i++)
        pointer[i] = "Number :" + std::to_string(i);

    std::cout << std::endl;

    for (size_t i = 0; i < size; i++)
        std::cout << pointer[i] << std::endl;
}

Большое спасибо.

Примечание:

Я пытался повторить это, создав шаблонный класс с лямбдой внутри (используя typedef), и это не сработало.

1 Ответ

1 голос
/ 31 марта 2020

Код имеет определенное поведение и работает нормально. С этим нет никаких проблем, за исключением того, что вы пропускаете последнее выделение, что не совсем оптимально (но законно). Добавьте delete[] pointer; в конце.


Версия массива new не возвращает вновь созданный массив или указатель или ссылку на него. Вместо этого он возвращает указатель на первый элемент во вновь созданном массиве.

pointer = new std::string[size];

После этого pointer будет указывать на первый std:.string из вновь созданного массива std::string[size]. Просто взглянув на pointer, вы не узнаете, является ли std::string, на который он указывает, частью массива или нет.

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

Вот почему вам, как программисту, нужно помнить, какой указатель указывает на один объект, выделенный с помощью new и какой из них указывает на массив, выделенный с помощью new[], и длину этого массива (поскольку в первом случае вам нужно удалить его с помощью delete, а во втором с delete[]).

На практике вы не должны использовать raw new как этот по этой причине (и другие). Вместо этого используйте контейнеры, такие как std::vector, если вам нужны массивы с динамическим размером, и std::unique_ptr, если вам нужны динамически размещаемые отдельные объекты (хотя существует также версия std::unique_ptr для массивов).

...