Здравствуйте, Pavel Dvorkin, Вы писали: PD>Здравствуйте, gegMOPO4, Вы писали: PD>>>Последнее есть просто передача указателя на массив. Память под массив там не отводится. MOP>>Да, именно так реализованы и локальные массивы нефиксированного размера. Это просто указатели. PD>Массив — это блок памяти, и его кто-то должен все же выделить.
Да. Выше я написал, где и как этот блок выделяется и как его используют.
MOP>>Вообще-то, во многих языках есть полноценные многомерные массивы нефиксированного размера. Это возможно. Массив «под капотом» будет реализован не только указателем на начало блока данных массива, но и целым размером его строки (а размер элемента известен на момент компиляции). PD>Вообще-то они есть в С/C++. Только не на стеке. Насчет того полноценныеони или нет — обсуждать не буду, пока не увижу определение , чем полноценные массивы отличаются от неполноценных PD>А вот если приведешь пример языка, где они реализованы именно на стеке — тогда и будет о чем говорить.
У вас ведь вроде были сомнения в возможности реализации в языке двумерных массивов с неизвестным во время компиляции размером?
>>>>Но кому это нужно и стоит ли такое узкое применение реализации? PD>>>Если разрешить динамические массивы — придется разрешить и динамические массивы из динамических массивов. Иначе архитектуре языка будет некоторое повреждение MOP>>Никакого повреждения, если понимать логику языка. Ну вот сейчас параметр функции можно объявить как int a[][42], но нельзя как int a[42][] — такого же типа «повреждение». PD>М-да. Может, все же разберешься сначала, почему нельзя...
Вообще-то, это у вас проблемы с пониманием синтаксиса и семантики C.
PD>>>И почему это узкое ? Еще какое широкое! Двумерные динамические матрицы встречаются сплошь и рядом (ну, правда, не в задачах создания сайтов . Хотя бы машинная графика. MOP>>Узкое потому, что нельзя этот массив передать наружу из функции. PD>Что узкое-то ? Двумерный против одномерного или динамический против фиксированной размерности ? Кстати, из функции вообще никакой массив передать наружу нельзя — еще не хватало передавать адрес локальной переменной после выхода из функции... static передать можно, но это дурной тон.
Кстати, static тоже нельзя. Узкое применение у двумерных массивов нефиксированного размера, которые необходимо размещать именно на стеке и обеспечить синтаксис двумерной индексации. По сравнению с ручной эмуляцией двумерного массива на одномерном, хоть на стеке, хоть где.
>>Нельзя иметь элементом структуры. PD>Это еще почему ? Нигде в С нет ограничений на тип элемента массива.
Потому, что размер структуры в текущем C должен быть известен на этапе компиляции.
>>Нельзя иметь глобальную переменную. PD>Несомненно. Хотел бы я посмотреть, как это можно в С присвоить значение размеру массива до начала выполнения программы.
Ну вот видите.
PD>Все, я закончил.
Если бы вы ещё больше думали и меньше троллили, я бы продолжил.
Здравствуйте, Muxa, Вы писали:
M>Я сейчас глупость спрошу: M>Почему нельзя сделать вот так?
M>
M>void f( int n )
M>{
M> int a[n];
M>}
M>
Причина идеологическая.
В ранних языках (Алгол-60, PL/1) это было можно
begin
integer n;
input(n);
begin
integer array a[1:n];
...
Впоследствии от этой идеи отказались.
За все компляторы и платформы, конечно, не скажу, ограничусь x86. Но, думаю, в других системах то же.
Когда все массивы статические, суммарный объем данных , размещаемых на стеке, при входе в функцию известен до ее выполнения. Поэтому компилятор просто строит код, изменяющий значение регистра стека на суммарный объем. Кстати, по крайней мере VC++ делает это именно при входе в функцию, а не при входе в блок, как вроде бы требовалось. Поэтому в пределах функции значение регистра стека не меняется (конечно, оно изменится, если внутри этой функции войти в другую, но тогда в другой будет то же самое, а выйдем — вернемся в исходное состояние вызываюшей функции). Поэтому адреса всех стековых переменных (и массивов, и скаляров) можно определить в момент входа в функцию и они в ней меняться не будут. В x86 для этого используется базирование по регистру EBP.
Если допустить, что память может внутри функции выделяться на переменный размер, то от этой простой схемы ничего не останется. Придется существенно усложнять код выделения, а значит, упадет скорость. Выгода не перекрывает проблем.
Здравствуйте, sysenter, Вы писали:
24>>В С стандарта 99-го года можно. В С++ впринципе можно шаблонами выкрутиться, как-то так (пишу в браузере): S>C++x11 вроде, как должен поддерживать т.к. совместим с C99.
Нет, было предложение включить VLA (variable length arrays) в C++11, но данное предложение не прошло.
Потенциальная возможность исчерпания стека и, как следствие, необходимость контролировать размер выделяемой памяти, потому что в Visual C++
A stack overflow exception is generated if the space cannot be allocated. The stack overflow exception is not a C++ exception; it is a structured exception.
На других платформах поведение вероятнее всего тоже будет неопределенным.
И что писать так?
void f(int n)
{
int* a;
if ( n <= SMALL_MAGIC_NUMBER )
{
a = alloca(n * sizeof(int));
}
else
{
a = new int[n]; // или выход с ошибкой
}
// работаем с a, но помним, что можем быть должны освободить память, т.е. никаких return и throw, только goto cleanup
// я люблю старый добрый C, ведь на нем пишет сам Торвальдс!
cleanup:
// нужно хорошо постараться, чтобы в С++ всегда попасть сюда при выходе из функции
// добро пожаловать в ручное управление памятью!if ( n > SMALL_MAGIC_NUMBER )
{
delete a;
}
}
Сравним с таким:
void f(int n)
{
std::vector<int> a(n);
// работаем с a, как обычным массивом, можно пользоваться throw и return, n может быть большим
}
На мой взгляд alloca — вредная функция. Если SMALL_MAGIC_NUMBER известен нам на этапе написания программы (из требований к исходной функции f), то можно использовать массив на стеке, иначе остается только std::vector или его аналоги с выделением памяти в куче.
1.9.1
The semantic descriptions in this International Standard define a parameterized nondeterministic abstract
machine. This International Standard places no requirement on the structure of conforming implementations.
1.9.7 An instance of each object with automatic storage duration (3.7.3) is associated with each entry into its
block. Such an object exists and retains its last-stored value during the execution of the block and while the
block is suspended (by a call of a function or receipt of a signal).
15.2.3
The process of calling destructors for automatic objects constructed on the path from a try block to a
throw-expression is called “stack unwinding.”
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Если допустить, что память может внутри функции выделяться на переменный размер, то от этой простой схемы ничего не останется. Придется существенно усложнять код выделения, а значит, упадет скорость. Выгода не перекрывает проблем.
Ой, да ладно. На входе сохраняем указатель стека в другом регистре и декрементируем его по мере надобности (напомню, стек на x86 растет вниз). На выходе восстанавливаем указатель стека из регистра. Команды enter/leave делают это автоматически.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, Ops, Вы писали: Ops>>Зачем вообще высокоуровневые языки, когда абсолютно все, что они могут, можно реализовать на асме?
MOP>Т.е. вы не понимаете, почему vector, string и iostream реализованы на C++, а не являются примитивами языка?
Я писал вот про это:
В то же время, потребности полностью удовлетворяются vector и scoped_array (возможно, с пользовательским аллокатором). Не менее (если не более) эффективно. Зачем вводить в язык синтаксическую конструкцию, если задачу можно решить существующими средствами?
Не удовлетворяются они, выделение памяти в хипе в многопоточном приложении всегда дорогая операция. Выделение на стеке — дешевая.
Можно заранее выделять память и в потоке раздавать уже ее, но зачем, когда есть стек — та же самая предвыделенная память?
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>В С++ же используй alloca для схожих целей:
АШ>
АШ>void foo(size_t size) {
АШ> int* a = new (alloca(size*sizeof(int))) int[size];
АШ> for(size_t i = 0; i < size; i++)
АШ> a[i] = 0;
АШ>}
АШ>
IMHO, в С++ alloca лучше не использовать. Он плохо взаимодействует с inline-подстановками, например...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, B0FEE664, Вы писали: BFE>>Здравствуйте, Ops, Вы писали: Ops>>>Зачем отдельную область аллокации, когда уже есть стек? BFE>>Как известно
, стандарт я ещё не прочитал. Вы уверены, что стек упоминается в стандарте С++ и обязателен при реализации ?
MOP>Да, в стандарте C++11 он упоминается. 23.6.5.
Это совсем другой стек
Здравствуйте, gegMOPO4, Вы писали:
Pzz>>У большинства, кстати, указателя стека именно что нету. В качестве такового используется регистр общего назначения.
MOP>Даже если это РОН, то РОН выделенный, зарезервированный для этой цели (как и указатель команд). Ведь у процессора есть и команда вызова подпрограммы, и прерывания.
Будете смеяться, специальной команды вызова подпрограммы может и не быть. А для обработки прерываний на архитектурах без встроенного аппаратного стека может использоваться механизм переключения банков регистров.
Здравствуйте, 24, Вы писали:
24>Здравствуйте, 24, Вы писали:
24>>В С++ впринципе можно шаблонами выкрутиться, как-то так (пишу в браузере):
24>С шаблонами так нельзя конечно, видимо я плохо выспался сегодня
если облажался, можно удалить топик как ошибочный.
Здравствуйте, Kernan, Вы писали:
24>>С шаблонами так нельзя конечно, видимо я плохо выспался сегодня K>если облажался, можно удалить топик как ошибочный.
Пока на него не ответили...
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Sni4ok, Вы писали:
S>Здравствуйте, Ops, Вы писали:
Ops>>Вроде в GСС можно (нестандартное расширение). А вообще для этих целей есть alloca.
S>а alloca по вашему- стандартная функция?
Нет, но поддерживается большинством компиляторов, в отличие от.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Sni4ok, Вы писали:
S>например затем, что выделение на стеке элементарная мгновенная операция, а выделение памяти под вектор очень дорогая конкурентная операция?
Не такая уж и дорогая. Понятное дело, что дороже чем выделение в стеке, но runtime библиотека имеет свой кеш памяти, чтобы каждый раз у системы не запрашивать, не фрагментировать и не требовать для пары байт целую страницу (4096). Обратно системе runtime библиотека так же возвращает не всю освободивщуюся память.
Здравствуйте, Muxa, Вы писали:
M>Я сейчас глупость спрошу: M>Почему нельзя сделать вот так? M>
M>void f( int n )
M>{
M> int a[n];
M>}
M>
А можно я глупый вопрос продолжу?
А почему нельзя как-то вынести на уровень языка динамическое добавление и извлечение объектов из системного стека? Многие алгоритмы таковы, что нужно насоздавать какое-то заранее неизвестное количество объектов из входных данных, и затем их обработать. На асме обычно пишут что-то типа "push eax" и все. А при выходе из фунцкии стек все равно восстанавливается.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>За все компляторы и платформы, конечно, не скажу, ограничусь x86. Но, думаю, в других системах то же.
PD>Когда все массивы статические, суммарный объем данных , размещаемых на стеке, при входе в функцию известен до ее выполнения. Поэтому компилятор просто строит код, изменяющий значение регистра стека на суммарный объем. Кстати, по крайней мере VC++ делает это именно при входе в функцию, а не при входе в блок, как вроде бы требовалось. Поэтому в пределах функции значение регистра стека не меняется (конечно, оно изменится, если внутри этой функции войти в другую, но тогда в другой будет то же самое, а выйдем — вернемся в исходное состояние вызываюшей функции). Поэтому адреса всех стековых переменных (и массивов, и скаляров) можно определить в момент входа в функцию и они в ней меняться не будут. В x86 для этого используется базирование по регистру EBP.
Именно! Именно ebp!
PD>Если допустить, что память может внутри функции выделяться на переменный размер, то от этой простой схемы ничего не останется. Придется существенно усложнять код выделения, а значит, упадет скорость. Выгода не перекрывает проблем.
Указатель на текущий фрейм стека сохраняется в ebp. Но выделение массива на стеке его не затрагивает, это выделение делается изменением регистра esp. Ну то есть адресация всех локальных переменных внутри функции никак не изменяется, она не зависит от esp, так как базой служит ebp, а на этот регистр стековые массивы никак не влияют. Никаких там падений скорости нет, код доступа к локальным переменным даже не меняется.
Здравствуйте, x-code, Вы писали:
XC>А почему нельзя как-то вынести на уровень языка динамическое добавление и извлечение объектов из системного стека? Многие алгоритмы таковы, что нужно насоздавать какое-то заранее неизвестное количество объектов из входных данных, и затем их обработать.
А по-твоему как функция printf работает? Поддержка переменного числа аргументов в функциях так и реализована в языке с самого начала.
XC>>А почему нельзя как-то вынести на уровень языка динамическое добавление и извлечение объектов из системного стека? Многие алгоритмы таковы, что нужно насоздавать какое-то заранее неизвестное количество объектов из входных данных, и затем их обработать. WM>А по-твоему как функция printf работает? Поддержка переменного числа аргументов в функциях так и реализована в языке с самого начала.
тем не менее в Си неполноценная поддержака этого.
Скажем, ты не можешь вызвать функцию с переменным и *динамически* определяемым кол-вом аргументов
Здравствуйте, Muxa, Вы писали: M>Почему нельзя сделать вот так?
Как выше уже отметили, в C99 можно. Почему же нельзя в C++ — тому две причины.
1. Для int, вроде, никаких проблем, как и для других POD, а вот насчёт классов с деструктором не уверен. Особенно учитывая исключения.
2. Если в функции есть массив переменного размера, то будет, как заметил Pavel Dvorkin, небольшой оверхед (даже если его не использовать).
В то же время, потребности полностью удовлетворяются vector и scoped_array (возможно, с пользовательским аллокатором). Не менее (если не более) эффективно. Зачем вводить в язык синтаксическую конструкцию, если задачу можно решить существующими средствами?
Здравствуйте, Pzz, Вы писали: Pzz>Ой, да ладно. На входе сохраняем указатель стека в другом регистре и декрементируем его по мере надобности (напомню, стек на x86 растет вниз). На выходе восстанавливаем указатель стека из регистра. Команды enter/leave делают это автоматически.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, watch-maker, Вы писали: WM>>Указатель на текущий фрейм стека сохраняется в ebp.
MOP>А ведь можно было бы и не сохранять. Вот на этом и оверхед.
Ну детский сад прямо. Этот оверхед — две инструкции. И во-первых, фреймы стека и так много где используются, независимо от поддержки VLA. Во вторых, компилятору ничего не мешает не включать фреймы, если в конкретной функции нет VLA. В-третьих, это всё равно в тысячи раз быстрее, чем выделение массива в куче.
Здравствуйте, watch-maker, Вы писали: WM>Здравствуйте, gegMOPO4, Вы писали: MOP>>Здравствуйте, watch-maker, Вы писали: WM>>>Указатель на текущий фрейм стека сохраняется в ebp. MOP>>А ведь можно было бы и не сохранять. Вот на этом и оверхед. WM>Ну детский сад прямо. Этот оверхед — две инструкции. И во-первых, фреймы стека и так много где используются, независимо от поддержки VLA. Во вторых, компилятору ничего не мешает не включать фреймы, если в конкретной функции нет VLA. В-третьих, это всё равно в тысячи раз быстрее, чем выделение массива в куче.
Не в тысячи, а всего лишь в 2-3 раза (или около того), если использовать специальный аллокатор. Притом в момент запроса (всё равно инициализация массива съест больше), а не при входе в функцию (даже если массив не понадобился).
И если практически того же самого легко добиться самому, то зачем менять язык? Он и так сложный.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, Pzz, Вы писали: Pzz>>Ой, да ладно. На входе сохраняем указатель стека в другом регистре и декрементируем его по мере надобности (напомню, стек на x86 растет вниз). На выходе восстанавливаем указатель стека из регистра. Команды enter/leave делают это автоматически.
MOP>А всё это лишние команды, лишние такты.
Указатель на стек на входе все равно удобно иметь под рукой, чтобы добираться до параметров. Большинство компиляторов все равно генерируют enter/leave (или эквиавалент), независимо от наличия alloca() или массивов переменной длинны
Здравствуйте, Pzz, Вы писали: Pzz>Здравствуйте, gegMOPO4, Вы писали: MOP>>Здравствуйте, Pzz, Вы писали: Pzz>>>Ой, да ладно. На входе сохраняем указатель стека в другом регистре и декрементируем его по мере надобности (напомню, стек на x86 растет вниз). На выходе восстанавливаем указатель стека из регистра. Команды enter/leave делают это автоматически. MOP>>А всё это лишние команды, лишние такты. Pzz>Указатель на стек на входе все равно удобно иметь под рукой, чтобы добираться до параметров. Большинство компиляторов все равно генерируют enter/leave (или эквиавалент), независимо от наличия alloca() или массивов переменной длинны
Указатель на стек всё равно есть в подавляющем большинстве современных платформ (у которых вообще есть стек). Обращаться по константному смещению от вершины стека одинаково удобно, независимо от количества локальных переменных. От дорогих enter/leave компиляторы избавляются при включенной оптимизации (особенно от конкретно enter/leave).
Здравствуйте, gegMOPO4, Вы писали:
MOP>В то же время, потребности полностью удовлетворяются vector и scoped_array (возможно, с пользовательским аллокатором). Не менее (если не более) эффективно. Зачем вводить в язык синтаксическую конструкцию, если задачу можно решить существующими средствами?
Зачем вообще высокоуровневые языки, когда абсолютно все, что они могут, можно реализовать на асме?
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>В x86 для этого используется базирование по регистру EBP.
Может использоваться базирование по EBP, для отладки; а так: omit frame pointer и вперед.
PD>Если допустить, что память может внутри функции выделяться на переменный размер, то от этой простой схемы ничего не останется. Придется существенно усложнять код выделения, а значит, упадет скорость. Выгода не перекрывает проблем.
Никто не требует размещать переменные в стеке в порядке их объявления и никто не запрещает размещать динамические массивы в стеке после всех остальных переменных.
Здравствуйте, watch-maker, Вы писали:
XC>>А почему нельзя как-то вынести на уровень языка динамическое добавление и извлечение объектов из системного стека? Многие алгоритмы таковы, что нужно насоздавать какое-то заранее неизвестное количество объектов из входных данных, и затем их обработать. WM>А по-твоему как функция printf работает? Поддержка переменного числа аргументов в функциях так и реализована в языке с самого начала.
Я говорю о прямом ручном размещении объкетов в стеке, через push, и извлечении через pop. Да, это небезопасно, можно случайно повредить стековые переменные или адрес возврата, но ведь на то он и Си чтобы быть небезопасным, да и чтобы повредить переменные есть гораздо более простые способы
Здравствуйте, gegMOPO4, Вы писали:
MOP>Указатель на стек всё равно есть в подавляющем большинстве современных платформ (у которых вообще есть стек). Обращаться по константному смещению от вершины стека одинаково удобно, независимо от количества локальных переменных. От дорогих enter/leave компиляторы избавляются при включенной оптимизации (особенно от конкретно enter/leave).
У большинства, кстати, указателя стека именно что нету. В качестве такового используется регистр общего назначения.
Компилятор избавляется от возни со стеком, если функция достаточно "простая" для этого. Наличие или отсутствие alloca или эквиавалента — лишь еще один критерий простоты.
Здравствуйте, watch-maker, Вы писали:
PD>>Если допустить, что память может внутри функции выделяться на переменный размер, то от этой простой схемы ничего не останется. Придется существенно усложнять код выделения, а значит, упадет скорость. Выгода не перекрывает проблем. WM>Указатель на текущий фрейм стека сохраняется в ebp. Но выделение массива на стеке его не затрагивает, это выделение делается изменением регистра esp. Ну то есть адресация всех локальных переменных внутри функции никак не изменяется, она не зависит от esp, так как базой служит ebp, а на этот регистр стековые массивы никак не влияют.
Отлично. Раскажи, как ты будешь получать доступ к локальным переменым через EBP, если при входе в функцию размещается два динамических массива. Они же тоже локальные переменные, к ним тоже надо добраться
PD>{
PD> int x;
PD> int y[n];
PD> {
PD> int z;
PD> int t[m];
PD>
PD>Кто тут после кого ?
push ebp
mov ebp,esp
sub esp,8
...
mov [ebp-4],eax ; x
mov [ebp-8],eax ; z
...
sub esp,N ; N=4*n
...
sub esp,M ; M=4*m
...
mov [ebp-4],eax ; по прежнему x
mov [ebp-8],eax ; по прежнему z
; т. о. имеем синтаксический оверхед только для самих динамических массивов
...
Проверял без фанатизма, но первый взгляд показал, что именно так — вполне логично как по мне — поступает MSVC++ при использовании alloca (выделяет переменные известного размера до переменного участка и использует ebp даже при указании omit frame pointers). В общем никакой сложности и оверхеда, ну разве что frame pointer теперь не можем опустить.
Здравствуйте, MescalitoPeyot, Вы писали:
MP>Здравствуйте, Pavel Dvorkin, Вы писали:
MP> ; т. о. имеем синтаксический оверхед только для самих динамических массивов
Не синтаксический. Обращаться к элементам массива как будешь ? Через ebp ? При том, что в стеке сейчас несколько массивов бог знает какой длины, к тому же при следующем вызове длины могут оказаться иными.
MP>Проверял без фанатизма, но первый взгляд показал, что именно так — вполне логично как по мне — поступает MSVC++ при использовании alloca (выделяет переменные известного размера до переменного участка и использует ebp даже при указании omit frame pointers). В общем никакой сложности и оверхеда, ну разве что frame pointer теперь не можем опустить.
А вот насчет использования ebp пожалуйста, подробнее. Я что-то не пойму, как можно обращаться к элементам нескольких подряд расположенных массивов переменной длины через одну базу, не зная их размеров.
Здравствуйте, PM, Вы писали: PM>На мой взгляд alloca — вредная функция. Если SMALL_MAGIC_NUMBER известен нам на этапе написания программы (из требований к исходной функции f), то можно использовать массив на стеке, иначе остается только std::vector или его аналоги с выделением памяти в куче.
Более того, с std::vector мы можем использовать пользовательский аллокатор, который при малом объёме будет выделять память в специальной заранее распределённой области (быстро, просто изменив пару указателей). Постойте-ка, да ведь стандартный аллокатор именно так и работает!
Здравствуйте, Pzz, Вы писали: Pzz>Здравствуйте, gegMOPO4, Вы писали: MOP>>Указатель на стек всё равно есть в подавляющем большинстве современных платформ (у которых вообще есть стек). Обращаться по константному смещению от вершины стека одинаково удобно, независимо от количества локальных переменных. От дорогих enter/leave компиляторы избавляются при включенной оптимизации (особенно от конкретно enter/leave). Pzz>У большинства, кстати, указателя стека именно что нету. В качестве такового используется регистр общего назначения.
Даже если это РОН, то РОН выделенный, зарезервированный для этой цели (как и указатель команд). Ведь у процессора есть и команда вызова подпрограммы, и прерывания.
Здравствуйте, Pavel Dvorkin, Вы писали: PD>Здравствуйте, MescalitoPeyot, Вы писали: >>и никто не запрещает размещать динамические массивы в стеке после всех остальных переменных. PD>После — это как ? PD>
PD>{
PD> int x;
PD> int y[n];
PD> {
PD> int z;
PD> int t[m];
PD>
PD>Кто тут после кого ?
Хм, думал, вы это понимаете. Компилятор резервирует на стеке место для следующих переменных постоянного размера:
int x;
int * y;
int z;
int * t;
А потом вызывает y = (int *)alloca(sizeof(int)*n) в начале функции и t = (int *)alloca(sizeof(int)*m) в начале блока. Для циклов придётся ещё и сохранять/восстанавливать стек для каждой итерации.
PD>А вот насчет использования ebp пожалуйста, подробнее. Я что-то не пойму, как можно обращаться к элементам нескольких подряд расположенных массивов переменной длины через одну базу, не зная их размеров.
Посмотрите как ведет себя MSVC++ при использовании alloca. Получает указатель для динамического блока и юзает непосредственно его. К остальным локальным переменным вне зависимости от места их объявления обращается при этом как и раньше, через ebp и постоянное смещение. Вот абсоютно также и будет делать в случае с динамическими массивами. К тому же на первый (и единственный, что очень часто бывает) динамический массивы вообще через esp обращаться можно. Короче, возьмите компилятор и посмотрите что он сделает с вашим фрагментом (только замените динамический массив на alloca или MSVC++ на GCC и volatil'ов каких-нибудь порасставляйте, чтоб никого не убило), все вопросы сразу отпадут.
Ваша ошибка, по-видимому, в том, что вы считаете что компилятор выделяет переменные в порядке объявления и в начале каждого блока. Однако это не так даже для дебажной сборки.
Здравствуйте, gegMOPO4, Вы писали:
MOP>1. Для int, вроде, никаких проблем, как и для других POD, а вот насчёт классов с деструктором не уверен. Особенно учитывая исключения.
Не уверен, что это проблема (вопрос нуждается в дополнительном исследовании), но в крайнем случае можно просто запретить динамические массивы с не-POD типами, точно также как это сделано для другой C-шной фичи, функций с переменным числом аргументов.
MOP>2. Если в функции есть массив переменного размера, то будет, как заметил Pavel Dvorkin, небольшой оверхед (даже если его не использовать).
Весь оверхед — обязательное занятие регистра ebp под frame pointer в таких функциях. В функциях где используются динамические массивы и (или) alloca он будет, где нет — нет будет. Напомню, к слову, что по-дефолту MSVC++ компиляет код в релизе с frame pointers.
Здравствуйте, MescalitoPeyot, Вы писали: MP>Здравствуйте, gegMOPO4, Вы писали: MOP>>Не в тысячи, а всего лишь в 2-3 раза (или около того), если использовать специальный аллокатор. MP>Я так понимаю этот аллокатор, который в 2-3 раза, еще и с потоками дружить не будет в отличии от.
Специальный — будет. Как для каждого потока отдельный стек, так и область аллокации будет отдельная.
Здравствуйте, MescalitoPeyot, Вы писали: MP>Здравствуйте, gegMOPO4, Вы писали: MOP>>Специальный — будет. Как для каждого потока отдельный стек, так и область аллокации будет отдельная. MP>А delet'ать как из другого потока?
Здравствуйте, gegMOPO4, Вы писали:
MOP>Мы о замене alloca, или уже о чём-то другом?
Просто ни alloca, ни динамический массив ни на что такое не претендуют, а аллокатор — это аллокатор, назвался аллокатором, будь добр, соответствуй. Что можно замутить свой пул на поток, а потом постоянно следить чтоб объект из него никуда случайно не передать и громко чесать репу при портировании на какой-нибудь без-TLS-ный Андроид, в этом я ничуть не сомневаюсь.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Хм, думал, вы это понимаете. Компилятор резервирует на стеке место для следующих переменных постоянного размера: MOP>int x; MOP>int * y; MOP>int z; MOP>int * t;
Тогда получится, что для массивов фиксированной длины имя массива есть константа, а для массивов переменной длины — нет. Боюсь, что это приведет к серьезной ревизии очень много в языке.
Кстати, сказав a, скажите и b. Как насчет многомерных массивов с переменной длиной ?
Здравствуйте, MescalitoPeyot, Вы писали:
PD>>А вот насчет использования ebp пожалуйста, подробнее. Я что-то не пойму, как можно обращаться к элементам нескольких подряд расположенных массивов переменной длины через одну базу, не зная их размеров.
MP>Посмотрите как ведет себя MSVC++ при использовании alloca. Получает указатель для динамического блока и юзает непосредственно его. К остальным локальным переменным вне зависимости от места их объявления обращается при этом как и раньше, через ebp и постоянное смещение. Вот абсоютно также и будет делать в случае с динамическими массивами. К тому же на первый (и единственный, что очень часто бывает) динамический массивы вообще через esp обращаться можно.
Именно на первый. На остальные нет, а при использовании _alloca будешь делать сам и помнить, где что.
MP>Ваша ошибка, по-видимому, в том, что вы считаете что компилятор выделяет переменные в порядке объявления и в начале каждого блока.
Я уже ответил раньше — не считаю. И никакой ошибки тут нет. Размещать переменные можно в любом порядке, независимо от описания, но если их размеры известны до входа в функцию, то для каждой переменной или члена массива известно его смещение от ebp и его можно записать в команде явно . Если неизвестны — нельзя (разве что для первого). От порядка размещения тут ничего не зависит.
Кстати, а как насчет многомерных динамических массивов ?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> Если неизвестны — нельзя (разве что для первого). От порядка размещения тут ничего не зависит.
Правильно это записывается так: "Можно для всех кроме второго и последующих динамических массивов, если они вообще есть". И в чем проблема? Духу плюсов ("не платить за то что не используешь") не противоречит, зато сохраняется совместимость с голыми сями.
PD>Кстати, а как насчет многомерных динамических массивов ?
А они разрешены? В любом случае проблемы проблемы не вижу.
Здравствуйте, Pavel Dvorkin, Вы писали: PD>Здравствуйте, gegMOPO4, Вы писали: MOP>>Хм, думал, вы это понимаете. Компилятор резервирует на стеке место для следующих переменных постоянного размера: MOP>>int x; MOP>>int * y; MOP>>int z; MOP>>int * t; PD>Тогда получится, что для массивов фиксированной длины имя массива есть константа, а для массивов переменной длины — нет. Боюсь, что это приведет к серьезной ревизии очень много в языке.
Массивы фиксированной длины и массивы переменной длины, которые появились в C99, — совсем разные вещи. Кстати, массивы как локальные переменные и массивы без указания размера как параметры функции тоже разные вещи. К серьёзной ревизии это не привело, ведь раньше такой сущности, как массив переменного размера, не было.
PD>Кстати, сказав a, скажите и b. Как насчет многомерных массивов с переменной длиной ?
Почему бы и нет? Но кому это нужно и стоит ли такое узкое применение реализации?
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, MescalitoPeyot, Вы писали: MP>>Здравствуйте, gegMOPO4, Вы писали: MOP>>>Не в тысячи, а всего лишь в 2-3 раза (или около того), если использовать специальный аллокатор. MP>>Я так понимаю этот аллокатор, который в 2-3 раза, еще и с потоками дружить не будет в отличии от.
MOP>Специальный — будет. Как для каждого потока отдельный стек, так и область аллокации будет отдельная.
Зачем отдельную область аллокации, когда уже есть стек?
Оккама на вас нет, он бы вам поотрезал сущности.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, MescalitoPeyot, Вы писали: MP>Здравствуйте, gegMOPO4, Вы писали: MOP>>Мы о замене alloca, или уже о чём-то другом? MP>Просто ни alloca, ни динамический массив ни на что такое не претендуют, а аллокатор — это аллокатор, назвался аллокатором, будь добр, соответствуй.
С чего бы это? Специализированный аллокатор или контейнер для замены массивов неконстантного размера (для тех, кого не устраивают стандартные) претендует только на замену массивов неконстантного размера.
MP>то можно замутить свой пул на поток, а потом постоянно следить чтоб объект из него никуда случайно не передать и громко чесать репу при портировании на какой-нибудь без-TLS-ный Андроид, в этом я ничуть не сомневаюсь.
А куда-нибудь случайно передать указатель на локальную переменную не боитесь?
Здравствуйте, Ops, Вы писали: Ops>Здравствуйте, gegMOPO4, Вы писали: MOP>>Здравствуйте, Ops, Вы писали: Ops>>>Зачем вообще высокоуровневые языки, когда абсолютно все, что они могут, можно реализовать на асме? MOP>>Т.е. вы не понимаете, почему vector, string и iostream реализованы на C++, а не являются примитивами языка? Ops>Я писал вот про это: Ops>
Ops>В то же время, потребности полностью удовлетворяются vector и scoped_array (возможно, с пользовательским аллокатором). Не менее (если не более) эффективно. Зачем вводить в язык синтаксическую конструкцию, если задачу можно решить существующими средствами?
Ops>Не удовлетворяются они, выделение памяти в хипе в многопоточном приложении всегда дорогая операция. Выделение на стеке — дешевая. Ops>Можно заранее выделять память и в потоке раздавать уже ее, но зачем, когда есть стек — та же самая предвыделенная память?
Затем, что это мы можем сделать прямо сейчас, существующими универсальными средствами языка, а вот выделять переменный размер на стеке — уже понадобиться вводить новую базовую фичу, менять грамматику языка. И очень специализированную фичу. Вот не было бы в языке классов, шаблонов, инлайна и перегрузки операторов — тогда это имело бы смысл. Но это не был бы C++.
Здравствуйте, Ops, Вы писали: Ops>Здравствуйте, gegMOPO4, Вы писали: MOP>>Здравствуйте, MescalitoPeyot, Вы писали: MP>>>Здравствуйте, gegMOPO4, Вы писали: MOP>>>>Не в тысячи, а всего лишь в 2-3 раза (или около того), если использовать специальный аллокатор. MP>>>Я так понимаю этот аллокатор, который в 2-3 раза, еще и с потоками дружить не будет в отличии от. MOP>>Специальный — будет. Как для каждого потока отдельный стек, так и область аллокации будет отдельная. Ops>Зачем отдельную область аллокации, когда уже есть стек? Ops>Оккама на вас нет, он бы вам поотрезал сущности.
Вот Оккам и режет. Зачем вводить специальный случай аллокации на стеке переменного размера (а к этому нужно обеспечить и вызовы деструкторов в нужном месте, и восстановление стека в циклах, и с инлайном не ошибиться) для реализации очень частного случая массивов переменного размера (которые и вовне функции не передашь, и размер не изменишь), когда уже существующими универсальными средствами можно легко реализовать как такие специальные ограниченны массивы, так и более универсальные?
Здравствуйте, MescalitoPeyot, Вы писали:
MP>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>> Если неизвестны — нельзя (разве что для первого). От порядка размещения тут ничего не зависит.
MP>Правильно это записывается так: "Можно для всех кроме второго и последующих динамических массивов, если они вообще есть". И в чем проблема?
В том, что придется менять и усложнять алгоритм доступа к второму и другим массивам. Не предлагаешь же ты запретить более одного динамического массива ?
>Духу плюсов ("не платить за то что не используешь") не противоречит, зато сохраняется совместимость с голыми сями.
Духами я не занимаюсь , а вот то, что от этой идеи отказались давным-давно — факт.
PD>>Кстати, а как насчет многомерных динамических массивов ?
MP>А они разрешены?
Здравствуйте, gegMOPO4, Вы писали:
MOP>Массивы фиксированной длины и массивы переменной длины, которые появились в C99, — совсем разные вещи. Кстати, массивы как локальные переменные и массивы без указания размера как параметры функции тоже разные вещи.
Последнее есть просто передача указателя на массив. Память под массив там не отводится.
PD>>Кстати, сказав a, скажите и b. Как насчет многомерных массивов с переменной длиной ?
MOP>Почему бы и нет?
А если да, то расскажи, как будешь доступ к ним осуществлять. Массив указателей создавать будешь при входе в функцию и заполнять его ?
>Но кому это нужно и стоит ли такое узкое применение реализации?
Если разрешить динамические массивы — придется разрешить и динамические массивы из динамических массивов. Иначе архитектуре языка будет некоторое повреждение
И почему это узкое ? Еще какое широкое! Двумерные динамические матрицы встречаются сплошь и рядом (ну, правда, не в задачах создания сайтов . Хотя бы машинная графика.
Здравствуйте, Pavel Dvorkin, Вы писали: PD>Здравствуйте, gegMOPO4, Вы писали: MOP>>Массивы фиксированной длины и массивы переменной длины, которые появились в C99, — совсем разные вещи. Кстати, массивы как локальные переменные и массивы без указания размера как параметры функции тоже разные вещи. PD>Последнее есть просто передача указателя на массив. Память под массив там не отводится.
Да, именно так реализованы и локальные массивы нефиксированного размера. Это просто указатели.
PD>>>Кстати, сказав a, скажите и b. Как насчет многомерных массивов с переменной длиной ? MOP>>Почему бы и нет? PD>А если да, то расскажи, как будешь доступ к ним осуществлять. Массив указателей создавать будешь при входе в функцию и заполнять его ?
Вообще-то, во многих языках есть полноценные многомерные массивы нефиксированного размера. Это возможно. Массив «под капотом» будет реализован не только указателем на начало блока данных массива, но и целым размером его строки (а размер элемента известен на момент компиляции).
>>Но кому это нужно и стоит ли такое узкое применение реализации? PD>Если разрешить динамические массивы — придется разрешить и динамические массивы из динамических массивов. Иначе архитектуре языка будет некоторое повреждение
Никакого повреждения, если понимать логику языка. Ну вот сейчас параметр функции можно объявить как int a[][42], но нельзя как int a[42][] — такого же типа «повреждение».
PD>И почему это узкое ? Еще какое широкое! Двумерные динамические матрицы встречаются сплошь и рядом (ну, правда, не в задачах создания сайтов . Хотя бы машинная графика.
Узкое потому, что нельзя этот массив передать наружу из функции. Нельзя иметь элементом структуры. Нельзя иметь глобальную переменную.
Здравствуйте, gegMOPO4, Вы писали:
PD>>Последнее есть просто передача указателя на массив. Память под массив там не отводится.
MOP>Да, именно так реализованы и локальные массивы нефиксированного размера. Это просто указатели.
Массив — это блок памяти, и его кто-то должен все же выделить.
MOP>Вообще-то, во многих языках есть полноценные многомерные массивы нефиксированного размера. Это возможно. Массив «под капотом» будет реализован не только указателем на начало блока данных массива, но и целым размером его строки (а размер элемента известен на момент компиляции).
Вообще-то они есть в С/C++. Только не на стеке. Насчет того полноценныеони или нет — обсуждать не буду, пока не увижу определение , чем полноценные массивы отличаются от неполноценных
А вот если приведешь пример языка, где они реализованы именно на стеке — тогда и будет о чем говорить.
>>>Но кому это нужно и стоит ли такое узкое применение реализации? PD>>Если разрешить динамические массивы — придется разрешить и динамические массивы из динамических массивов. Иначе архитектуре языка будет некоторое повреждение
MOP>Никакого повреждения, если понимать логику языка. Ну вот сейчас параметр функции можно объявить как int a[][42], но нельзя как int a[42][] — такого же типа «повреждение».
М-да. Может, все же разберешься сначала, почему нельзя...
PD>>И почему это узкое ? Еще какое широкое! Двумерные динамические матрицы встречаются сплошь и рядом (ну, правда, не в задачах создания сайтов . Хотя бы машинная графика.
MOP>Узкое потому, что нельзя этот массив передать наружу из функции.
Что узкое-то ? Двумерный против одномерного или динамический против фиксированной размерности ? Кстати, из функции вообще никакой массив передать наружу нельзя — еще не хватало передавать адрес локальной переменной после выхода из функции... static передать можно, но это дурной тон.
>Нельзя иметь элементом структуры.
Это еще почему ? Нигде в С нет ограничений на тип элемента массива.
>Нельзя иметь глобальную переменную.
Несомненно. Хотел бы я посмотреть, как это можно в С присвоить значение размеру массива до начала выполнения программы.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Затем, что это мы можем сделать прямо сейчас, существующими универсальными средствами языка, а вот выделять переменный размер на стеке — уже понадобиться вводить новую базовую фичу, менять грамматику языка. И очень специализированную фичу. Вот не было бы в языке классов, шаблонов, инлайна и перегрузки операторов — тогда это имело бы смысл. Но это не был бы C++.
Слава яйцам, что не Вы решаете, что нужно в стандарте, иначе бы мы не только лямбд не дождались, но и шаблонов бы не увидели.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Ops, Вы писали: Ops>Здравствуйте, gegMOPO4, Вы писали: MOP>>Затем, что это мы можем сделать прямо сейчас, существующими универсальными средствами языка, а вот выделять переменный размер на стеке — уже понадобиться вводить новую базовую фичу, менять грамматику языка. И очень специализированную фичу. Вот не было бы в языке классов, шаблонов, инлайна и перегрузки операторов — тогда это имело бы смысл. Но это не был бы C++. Ops>Слава яйцам, что не Вы решаете, что нужно в стандарте, иначе бы мы не только лямбд не дождались, но и шаблонов бы не увидели.
Укажете пункт стандарта, в котором описаны локальные массивы нефиксированной длины?
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, Ops, Вы писали: Ops>>Здравствуйте, gegMOPO4, Вы писали: MOP>>>Затем, что это мы можем сделать прямо сейчас, существующими универсальными средствами языка, а вот выделять переменный размер на стеке — уже понадобиться вводить новую базовую фичу, менять грамматику языка. И очень специализированную фичу. Вот не было бы в языке классов, шаблонов, инлайна и перегрузки операторов — тогда это имело бы смысл. Но это не был бы C++. Ops>>Слава яйцам, что не Вы решаете, что нужно в стандарте, иначе бы мы не только лямбд не дождались, но и шаблонов бы не увидели.
MOP>Укажете пункт стандарта, в котором описаны локальные массивы нефиксированной длины?
Ну и я об этом. Если бы Вы решали — там бы и пунктов про шаблоны не было.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, 24, Вы писали:
24>В С стандарта 99-го года можно.
+1
24>В С++ впринципе можно шаблонами выкрутиться, как-то так (пишу в браузере): 24>
24>template <typename T, int SIZE>
24>class Array {
24>public:
24> T& operator[](int i) {return data[i];}
24>private:
24> T data[SIZE];
24>}
24>void f( int n )
24>{
24> Array<int, n> a;
24>}
24>
А так, вроде бы нельзя...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, panter_dsd, Вы писали: M>>Почему нельзя сделать вот так?
M>>
M>>void f( int n )
M>>{
M>> int a[n];
M>>}
M>>
_>А зачем, если есть std::vector?
Например, для эффективности...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Ops, Вы писали: Ops>Здравствуйте, gegMOPO4, Вы писали: MOP>>Здравствуйте, Ops, Вы писали: Ops>>>Здравствуйте, gegMOPO4, Вы писали: MOP>>>>Затем, что это мы можем сделать прямо сейчас, существующими универсальными средствами языка, а вот выделять переменный размер на стеке — уже понадобиться вводить новую базовую фичу, менять грамматику языка. И очень специализированную фичу. Вот не было бы в языке классов, шаблонов, инлайна и перегрузки операторов — тогда это имело бы смысл. Но это не был бы C++. Ops>>>Слава яйцам, что не Вы решаете, что нужно в стандарте, иначе бы мы не только лямбд не дождались, но и шаблонов бы не увидели. MOP>>Укажете пункт стандарта, в котором описаны локальные массивы нефиксированной длины? Ops>Ну и я об этом. Если бы Вы решали — там бы и пунктов про шаблоны не было.
Я вам излагаю причины, по которым этого в стандарте нет, а вы о чём?
Или не приписав собеседнику какую-то очевидно бредовую мысль (я ведь ничего не говорил о своём отношении к шаблонам и массивам переменного размера) и не развенчав её, день пропал зря?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Если допустить, что память может внутри функции выделяться на переменный размер, то от этой простой схемы ничего не останется. Придется существенно усложнять код выделения, а значит, упадет скорость. Выгода не перекрывает проблем.
Странно как-то, в С перекрывает, занчит, а в С++ нет?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, gegMOPO4, Вы писали:
MOP>Мы о замене alloca, или уже о чём-то другом?
Ты, вроде как о std::vector с каким-то хитрым аллокатором...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Тогда получится, что для массивов фиксированной длины имя массива есть константа, а для массивов переменной длины — нет.
почему это? И то и то раз проинициализированное, уже никогда не меняется. При этом, так как переменная автоматическая, то константа времени исполнения, а не компиляции...
PD>Боюсь, что это приведет к серьезной ревизии очень много в языке.
Вряд ли.
PD>Кстати, сказав a, скажите и b. Как насчет многомерных массивов с переменной длиной ?
А как в С99 сделано?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали: E>Здравствуйте, Pavel Dvorkin, Вы писали: PD>>Если допустить, что память может внутри функции выделяться на переменный размер, то от этой простой схемы ничего не останется. Придется существенно усложнять код выделения, а значит, упадет скорость. Выгода не перекрывает проблем. E>Странно как-то, в С перекрывает, занчит, а в С++ нет?..
В C нет классов, шаблонов и перегрузки операторов — выгода больше (а проблем меньше).
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, Ops, Вы писали: Ops>>Здравствуйте, gegMOPO4, Вы писали: MOP>>>Здравствуйте, Ops, Вы писали: Ops>>>>Здравствуйте, gegMOPO4, Вы писали: MOP>>>>>Затем, что это мы можем сделать прямо сейчас, существующими универсальными средствами языка, а вот выделять переменный размер на стеке — уже понадобиться вводить новую базовую фичу, менять грамматику языка. И очень специализированную фичу. Вот не было бы в языке классов, шаблонов, инлайна и перегрузки операторов — тогда это имело бы смысл. Но это не был бы C++. Ops>>>>Слава яйцам, что не Вы решаете, что нужно в стандарте, иначе бы мы не только лямбд не дождались, но и шаблонов бы не увидели. MOP>>>Укажете пункт стандарта, в котором описаны локальные массивы нефиксированной длины? Ops>>Ну и я об этом. Если бы Вы решали — там бы и пунктов про шаблоны не было.
MOP>Я вам излагаю причины, по которым этого в стандарте нет, а вы о чём?
Вы излагаете то, что Вам кажется, а не причины. Я не вижу серьезных проблем с добавлением подобной фичи в язык. В GCC же сделали, не затронув всего языка, и ни классы, ни шаблоны этому не помешали. От Вас — ни одного аргумента против, только утверждения, что лучше все делать "существующими универсальными средствами языка".
MOP>Или не приписав собеседнику какую-то очевидно бредовую мысль (я ведь ничего не говорил о своём отношении к шаблонам и массивам переменного размера) и не развенчав её, день пропал зря?
Дальше спорить не хочу, т.к. бесполезно.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Ops, Вы писали: MOP>>>>Укажете пункт стандарта, в котором описаны локальные массивы нефиксированной длины? Ops>>>Ну и я об этом. Если бы Вы решали — там бы и пунктов про шаблоны не было. MOP>>Я вам излагаю причины, по которым этого в стандарте нет, а вы о чём? Ops>Вы излагаете то, что Вам кажется, а не причины. Я не вижу серьезных проблем с добавлением подобной фичи в язык. В GCC же сделали, не затронув всего языка, и ни классы, ни шаблоны этому не помешали. От Вас — ни одного аргумента против, только утверждения, что лучше все делать "существующими универсальными средствами языка".
Если вас не устраивает этот ниодин аргумент, то вам, безусловно, нетрудно будет привести настоящие причины, по которым в языке C++ до сих пор нет массивов с неконстантным количеством элементов.
Ops>Дальше спорить не хочу, т.к. бесполезно.
Вот это правильно, и не нужно было спорить о вещах, в которых не разбираетесь.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Т.е. вы не понимаете, почему vector, string и iostream реализованы на C++, а не являются примитивами языка?
С такой точки зрения нам и переменное число аргументов не нужно: я и на std::stack<boost::any> printf набросать смогу. Кроме того, не видел ни одного плюсового компилятора, который не умеет компилить сишный код, так что у всех кто собирается поддерживать новейший прям только вчера принятый С99 эта фича будет работать из коробки.
Здравствуйте, MescalitoPeyot, Вы писали: MP>Здравствуйте, gegMOPO4, Вы писали: MOP>>Т.е. вы не понимаете, почему vector, string и iostream реализованы на C++, а не являются примитивами языка? MP>С такой точки зрения нам и переменное число аргументов не нужно: я и на std::stack<boost::any> printf набросать смогу.
printf уже был в C, и широко использовался. Пришлось поддерживать. А так, конечно, эллипсис (в том виде, как пришёл из C) — зло. Но с этим ничего не поделаешь.
MP>Кроме того, не видел ни одного плюсового компилятора, который не умеет компилить сишный код, так что у всех кто собирается поддерживать новейший прям только вчера принятый С99 эта фича будет работать из коробки.
C++ разрабатывался (почти) совместимым с тогдашним C, чтобы можно было использовать уже наработанный код и плавно переходить к использованию достоинств C++. Для C99 такой проблемы нет — те, кто почему-то используют C99 (а не ограниченное подмножество C++), в курсе, какие фичи несовместимы с C++, да и кода такого мало.
Компиляторы C++ не обязательно поддерживают C99. И необязательно смешивание C++ и C99 безопасно.