динамическое выделение памяти, куча, косвенность, NULL

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

Я попробовал следующее

template<typename T>
[...something here...]
T *mem = new T[size];

for ( int i=0; i<size; i++ )
{
(mem+i) = NULL;
}
[...something else there...]

Так же, как можно было бы написать

int *pInt = new int;
pInt = NULL;

Но это не работает, потому что в верхнем примере mem не «lvalue»?

Почему это происходит только в том случае, если я динамически выделяю больше памяти для каждого типа в куче?

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

template<typename T>
[...something here...]
T mem = new T[size];

for ( int i=0; i<size; i++ )
{
*(mem+i) = NULL;

/* or the equivalent
mem[i] = NULL;
*/
}
[...something else there...]

Как это может быть возможно назначить NULL (который в основном int значение 0) для переменной или объекта, который может быть в основном что-нибудь? Это может быть int переменная, хорошо, это будет работать. Но что, если я вызвал функцию шаблона с std::string, Это не должно работать вообще, верно? Так почему кажется законным написать что-то подобное?

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

0

Решение

Но это не работает, потому что в верхнем примере «mem» не является «lvalue»?

Действительно, вы пытаетесь переназначить временный указатель mem+i; это не имеет смысла. Предположительно, вы хотите установить член массива (mem[i] или же *(mem+i)) к чему-то; хотя, вероятно, не NULL если T должен быть указателем типа.

В примере с одним объектом вы переназначаете единственный указатель на выделенный объект; поэтому у вас нет возможности использовать или удалить объект.

Как может быть возможно присвоить NULL (который, по сути, является значением int 0) переменной или объекту, который может быть чем угодно?

Потому что до C ++ 11 единственные допустимые константы нулевого указателя (и, следовательно, единственные допустимые расширения NULL macro) были целочисленными константами с нулевым значением; поэтому код расширяется до чего-то вроде

*(mem+i) = 0;

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

Но что, если бы я вызвал функцию шаблона с помощью std :: string. Это не должно работать вообще, верно?

std::string имеет конструктор и оператор присваивания, принимающий указатель на строку в стиле C, например,

std::string hello = "Hello, world!";

Они также могут принимать нулевой указатель, давая неопределенное поведение.

1

Другие решения

Ваш код:

for ( int i=0; i<size; i++ )
{
(mem+i) = NULL;
}

В этом случае (mem+i) является временным результатом и называется rvalue. Значения являются временными, вы не должны присваивать им значение. Вы можете назначить значение только lvalue. (Кстати, я думаю, что это не то, что вы хотите сделать: я думаю, вы хотите изменить память, на которую указывает указатель, а не значение адреса, хранящееся в указателе)

for ( int i=0; i<size; i++ )
{
mem[i] = NULL;
*(mem+i) = NULL;
}

В этом случае также вычисляются временные результаты (в обоих случаях mem+i) но они используются для адресации правильной памяти. Таким образом, в обоих случаях указанная память является lvalue.

Если вы используете шаблоны, вы должны помнить, что это шаблоны 😉
Код шаблона никогда не компилируется, если шаблон нигде не используется. И если он используется, это зависит от того, какую переменную / класс вы используете в качестве аргумента шаблона.

Вы можете написать этот код:

template<typename T>
void func( T a)
{
a.foo = "bar";
a.my_func( 3.14);
}

Этот код выглядит странно, но он будет компилироваться для каждого a которая имеет любую структуру или класс с переменной / объектом-членом foo что может быть назначено const charи функция-член или указатель на функцию или объект с перегруженным operator () с именем my_func,

0

По вопросам рекламы [email protected]