Как delete [] знает, что это массив?

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

B channel

И ваш альфа-канал выглядит так

alpha channel

[ 1112] Чтобы достичь того, что вам нужно, вам нужно применить некоторую матричную математику, чтобы получить свой результат. Я приложил код здесь

import cv2
import matplotlib.pyplot as plt

img_path = r"path/to/image"

#saving image into a white bg
img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
plt.imshow(img)
plt.show()
b,g,r, a = cv2.split(img)
print(img.shape)

new_img  = cv2.merge((b, g, r))
not_a = cv2.bitwise_not(a)
not_a = cv2.cvtColor(not_a, cv2.COLOR_GRAY2BGR)
plt.imshow(not_a)
plt.show()
new_img = cv2.bitwise_and(new_img,new_img,mask = a)
new_img = cv2.add(new_img, not_a)

cv2.imwrite(output_dir, new_img)
plt.imshow(new_img)
print(new_img.shape)
plt.show()

В результате получилось изображение с размерами (1200, 1200, 3)

enter image description here

135
задан Aaron McDaid 2 October 2016 в 11:57
поделиться

10 ответов

Компилятор не знает, что это - массив, это доверяет программисту. Удаление указателя на сингл int с delete [] привел бы к неопределенному поведению. Ваша секунда main() пример небезопасен, даже если он сразу не отказывает.

Компилятор действительно должен отслеживать то, сколько объектов должно быть удалено так или иначе. Это может сделать это путем сверхвыделения достаточно для хранения размера массива. Для получения дополнительной информации посмотрите C++ Супер FAQ.

99
ответ дан 23 November 2019 в 23:45
поделиться

delete или delete [] , вероятно, оба освободят выделенную память (память указана ), но большая разница в том, что delete в массиве не вызовет деструктор каждого элемента массива.

В любом случае, смешивая new / new [] и delete / delete [] , вероятно, UB.

9
ответ дан 23 November 2019 в 23:45
поделиться

Это очень похоже на этот вопрос, и он имеет многие детали Ваш, ищут.

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

Это видимо на некоторых реализациях путем выполнения следующего кода

int* pArray = new int[5];
int size = *(pArray-1);
13
ответ дан 23 November 2019 в 23:45
поделиться

Вы не можете использовать delete для массива, и вы не можете использовать delete [] для не-массива.

0
ответ дан 23 November 2019 в 23:45
поделиться

Это не знает, что это - массив, вот почему необходимо предоставить delete[] вместо старого регулярного delete.

6
ответ дан 23 November 2019 в 23:45
поделиться

Да, ОС сохраняет некоторые вещи в 'фоне'. Например, если Вы работаете

int* num = new int[5];

ОС может выделить 4 дополнительных байта, сохранить размер выделения в первых 4 байтах выделенной памяти и возвратить указатель смещения (т.е., это выделяет пространства памяти 1 000 - 1 024, но указатель возвратил точки 1 004 с местоположениями 1000-1003 хранения размера выделения). Затем когда удаляют, назван, это может посмотреть на 4 байта, прежде чем указатель передал ему для нахождения размера выделения.

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

27
ответ дан 23 November 2019 в 23:45
поделиться

Один вопрос, который ответы, данные до сих пор, кажется, не рассматривают: если библиотеки времени выполнения (не ОС, действительно) могут отслеживать количество вещей в массиве, то, почему нам нужно delete[] синтаксис вообще? Почему не может сингл delete сформируйтесь использоваться для обработки, все удаляет?

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

Таким образом, если Ваш код просто делает

Foo* foo = new Foo;

затем пространство памяти это выделяется для foo не должен включать дополнительные издержки, которые будут необходимы для поддержки массивов Foo.

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

delete[] bar;

вместо просто

delete bar;

если панель является указателем на массив.

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

103
ответ дан 23 November 2019 в 23:45
поделиться

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

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

3
ответ дан 23 November 2019 в 23:45
поделиться

семантически, обе версии оператора удаления в C ++ могут «есть» любой указатель; Однако, если указатель на один объект отдается Удалить [] [] , то Ub приведет к тому, что может произойти что-то, в том числе систему сбой или вообще ничего.

C ++ требует, чтобы программитор выбрал правильную версию оператора удаления в зависимости от объекта DealLocation: массив или один объект.

Если компилятор может автоматически определить, прошел ли указатель к оператору удаления, был указательным массивом, то будет только один оператор удаления в C ++, что было бы только для обоих случаев.

1
ответ дан 23 November 2019 в 23:45
поделиться

У меня был похожий вопрос. В Си вы выделяете память с помощью malloc() (или другой аналогичной функции), а удаляете ее с помощью free(). Есть только одна malloc(), которая просто выделяет определенное количество байт. Есть только одна функция free(), которая просто принимает в качестве параметра указатель.

Так почему же в C можно просто передать указатель free, а в C++ нужно сказать, массив это или одна переменная?

Ответ, как я узнал, связан с деструкторами класса.

Если выделить экземпляр класса MyClass...

classes = new MyClass[3];

И удалить его с помощью delete, то можно получить деструктор только для первого вызываемого экземпляра класса MyClass. Если Вы используете delete[], то можете быть уверены, что деструктор будет вызван для всех экземпляров массива.

В этом и заключается важная разница. Если вы просто работаете со стандартными типами (например, int), то на самом деле вы не увидите этой проблемы. Кроме того, следует помнить, что поведение при использовании delete на new[] и delete[] на new неопределенно - оно может работать не одинаково на всех компиляторах/системах.

5
ответ дан 23 November 2019 в 23:45
поделиться
Другие вопросы по тегам:

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