Позже версии GCC правильно реализуют стандарт.
стандарт определяет, что дисквалифицированные имена в шаблоне независимы и должны искаться, когда шаблон определяется. Определение зависимого базового класса неизвестно в то время (специализации шаблона базового класса могут существовать), таким образом, дисквалифицированные имена неспособны быть разрешенными.
Это верно и для имен переменной и для имен функций, объявленных в базовом классе.
, Как Вы заметили, решение состоит в том, чтобы обеспечить полностью определенное имя переменной или функции, или обеспечить объявление "использования". Например,
template<class T>
int Bar<T>::Perna(int u)
{
int c = Foo<T>::a * 4; // This works
c = this->a * 4; // and this
using Foo<T>::a;
c = a * 4; // and with 'using', so should this
}
(я на самом деле не на 100% уверен в правильном синтаксисе для версии использования и не могу протестировать отсюда, но Вы получаете идею).
Есть несколько причин:
malloc
/ calloc
до free
); Без гибкого времени жизни объекта полезные структуры данных, такие как двоичные деревья и связанные списки, были бы фактически невозможно написать.
Большой - №1. Как только вы попадете в какой-либо вид параллелизма, или IPC # 1 повсюду. Даже самые нетривиальные однопоточные приложения сложно разработать без выделения некоторой кучи. Это практически имитирует функциональный язык C / C ++.
So I want to make a string. I can make it on the heap or on the stack. Let's try both:
char *heap = malloc(14);
if(heap == NULL)
{
// bad things happened!
}
strcat(heap, "Hello, world!");
And for the stack:
char stack[] = "Hello, world!";
So now I have these two strings in their respective places. Later, I want to make them longer:
char *tmp = realloc(heap, 20);
if(tmp == NULL)
{
// bad things happened!
}
heap = tmp;
memmove(heap + 13, heap + 7);
memcpy(heap + 7, "cruel ", 6);
And for the stack:
// umm... What?
This is only one benefit, and others have mentioned other benefits, but this is a rather nice one. With the heap, we can at least try to make our allocated space larger. With the stack, we're stuck with what we have. If we want room to grow, we have to declare it all up front, and we all know how it stinks to see this:
char username[MAX_BUF_SIZE];
Наиболее очевидное обоснование использования кучи - это когда вы вызываете функцию и вам нужно вернуть что-то неизвестной длины. Иногда вызывающий может передать блок памяти и размер функции, но в других случаях это просто непрактично, особенно если возвращаемый материал является сложным (например, набор различных объектов с летающими указателями и т. Д.).
just to add you can use alloca to allocate memory on the stack, but again memory on the stack is limited and also the space exists only during the function execution only. that does not mean everything should be allocated on the heap. like all design decisions this is also somewhat difficult, a "judicious" combination of both should be used.
Size limits are a huge dealbreaker in a lot of cases. The stack is usually measured in the low megabytes or even kilobytes (that's for everything on the stack), whereas all modern PCs allow you a few gigabytes of heap. So if you're going to be using a large amount of data, you absolutely need the heap.
Stack variables (often called 'automatic variables') is best used for things you want to always be the same, and always be small.
int x;
char foo[32];
Are all stack allocations, These are fixed at compile time too.
The best reason for heap allocation is that you cant always know how much space you need. You often only know this once the program is running. You might have an idea of limits but you would only want to use the exact amount of space required.
If you had to read in a file that could be anything from 1k to 50mb, you would not do this:-
int readdata ( FILE * f ) {
char inputdata[50*1024*1025];
...
return x;
}
That would try to allocate 50mb on the stack, which would usually fail as the stack is usually limited to 256k anyway.
Стек и куча имеют одно и то же «открытое» пространство памяти и в конечном итоге должны прийти к точке, где они встречаются, если вы используете весь сегмент памяти. Сохранение баланса между пространством, которое использует каждый из них, будет иметь амортизированную стоимость позже для выделения и освобождения памяти с меньшим асимптотическим значением.
Besides manual control of object's lifetime (which you mentioned), the other reasons for using heap would include:
For example, you can allocate an array of certain size, which is only known at run time.
With the introduction of VLA (Variable Length Arrays) in C99, it became possible to allocate arrays of fixed run-time size without using heap (this is basically a language-level implementation of 'alloca' functionality). However, in other cases you'd still need heap even in C99.
For example, when you build a binary tree stucture, you can't meaningfully allocate the nodes of the tree on the stack in advance. You have to use heap to allocated them "on demand".
When you need a large, say, I/O buffer, even for a short time (inside a single function) it makes more sense to request it from the heap instead of declaring a large automatic array.