Когда Вы использовали бы массив, а не вектор/строку?

Шаг 1 запустите:

composer install

Шаг 2:

php artisan key:generate

должно работать

11
задан Skilldrick 27 February 2009 в 12:17
поделиться

8 ответов

Когда написание кода, которое должно используемый в других проектах, в особенности если Вы нацелены на специальные платформы (встроенный, игровые приставки, и т.д.), где STL не мог бы присутствовать.

Старые проекты или проекты с особыми требованиями не могли бы хотеть представлять зависимости от библиотек STL. Интерфейс в зависимости от массивов, символ* или независимо от того, что будет совместимо с чем-либо, так как это - часть языка. STL однако, как гарантируют, не будет присутствовать во всех средах сборки.

17
ответ дан 3 December 2019 в 01:02
поделиться

Я предлагаю использовать массивы каждый раз, когда Вы знаете размер в само время компиляции. Хотя вектор может использоваться, мы должны помнить, что вектор идет со своими издержками, связанными с выделением памяти, сделанным на "куче". Если размер не известен, то, конечно, векторы использования.

3
ответ дан 3 December 2019 в 01:02
поделиться

Я вижу два основания:

  1. Совместимость (старый код без STL).
  2. Скорость. (Я сравнил скорость использования vector/binary_search, и выстраивайте/пишите от руки двоичный поиск. Для последнего был получен ужасный код (с перераспределением памяти), но это было приблизительно в 1.2-1.5 раза быстрее затем сначала один, я использовал MS VC ++ 8)
1
ответ дан 3 December 2019 в 01:02
поделиться

Единственной причиной, о которой я мог думать, будет скорость. Можно сделать лучшую оптимизацию на массиве/типах указателей, чем на согласно объектам. Но я даже использовал бы STL, если я, absoluteltely знал объем данных мои структуры данных, должен держать. Изменение от STL до типов примитивов на шаге оптимизации лучше, чем запуск проекта с более твердым к чтению кодом.

1
ответ дан 3 December 2019 в 01:02
поделиться

Массив/символ* полезен, когда совместимость или производительность имеют очень высокий приоритет. Векторы и Строки являются объектами более высокого уровня, которые лучше, когда надежность кода, удобочитаемость и полная легкость рассчитывают. Почти всегда это.

4
ответ дан 3 December 2019 в 01:02
поделиться

Никогда.

Если необработанный массив кажется лучшим решением, чем вектор (по причинам другой сказанный здесь) затем, я использую станд.:: tr1:: массив или станд.:: массив в C++ 11 компиляторов (или повышение:: массив). Это просто делает проверки, которые я сделал бы так или иначе, чтобы быть уверенным, и использование значения размера делает DRY автоматически реализованным (например, я использую размер в циклах так, чтобы будущие изменения объявления массива автоматически работали).

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

И это работает очень хорошо с алгоритмами STL (при наличии).

Теперь, существует два случая, где необходимо использовать необработанные массивы (обязательство): когда Вы находитесь в коде C-only (не общающийся с C код, но пишущий в части C-only кода, как библиотека C). Но затем это - другой язык.

Другая причина состоит в том, когда компилятор не поддерживает шаблоны вообще...

15
ответ дан 3 December 2019 в 01:02
поделиться

Этот вопрос мог на самом деле быть разделен на две части:

  1. Как я должен управлять памятью для данных плоской антенной решетки?
  2. Как я должен получить доступ к элементам плоской антенной решетки?

Я лично предпочитаю использовать станд.:: вектор для руководящей памяти кроме случаев, где я должен поддержать совместимость с кодом, который не использует STL (т.е. при взаимодействии через интерфейс с прямым кодом C). Намного более трудно сделать безопасный от исключения код с необработанными массивами выделенным через новый или malloc (частично, потому что действительно легко забыть, что необходимо волноваться об этом). См. любую статью о RAII по причинам.

На практике, станд.:: вектор реализован как плоская антенная решетка. По сути, всегда возможно вытащить необработанный массив и использовать схемы доступа C-стиля. Я обычно запускаю с векторного нижнего синтаксиса оператора. Для некоторых компиляторов, при создании отладочной версии, векторы обеспечивают автоматическую граничную проверку. Это медленно (часто 10x замедление для жестких циклов), но полезно в нахождении определенных типов ошибок.

Если профилирование на конкретной платформе указывает, что оператор [] является узким местом, то я переключаюсь на прямой доступ к необработанному массиву. Интересно, в зависимости от компилятора и ОС, это может иногда быть быстрее для использования вектора STL, чем необработанный массив.

Вот некоторые результаты простого тестового приложения. Это было скомпилировано с Visual Studio 2008 в 32-разрядном режиме Release с помощью/O2 оптимизацию и работавший Vista x64. Подобные результаты достигаются с 64-разрядным тестовым приложением.

Binary search...
           fill vector (for reference) :  0.27 s
                   array with ptr math :  0.38 s <-- C-style pointers lose
                  array with int index :  0.23 s <-- [] on raw array wins
            array with ptrdiff_t index :  0.24 s
                 vector with int index :  0.30 s  <-- small penalty for vector abstraction
           vector with ptrdiff_t index :  0.30 s

Counting memory (de)allocation...
                memset (for reference) :  2.85 s
      fill malloc-ed raw array with [] :  2.66 s
     fill malloc-ed raw array with ptr :  2.81 s
         fill new-ed raw array with [] :  2.64 s
        fill new-ed raw array with ptr :  2.65 s
                  fill vector as array :  3.06 s  \ something's slower 
                           fill vector :  3.05 s  / with vector!

NOT counting memory (de)allocation...
                memset (for reference) :  2.57 s
      fill malloc-ed raw array with [] :  2.86 s
     fill malloc-ed raw array with ptr :  2.60 s
         fill new-ed raw array with [] :  2.63 s
        fill new-ed raw array with ptr :  2.78 s
                  fill vector as array :  2.49 s \ after discounting the  
                           fill vector :  2.54 s / (de)allocation vector is faster!

Код:

#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#include <string>
#include <vector>
#include <stdio.h>

using namespace std;

__int64 freq; // initialized in main
int const N = 1024*1024*1024/sizeof(int)/2; // 1/2 GB of data
int const nIter = 10;

class Timer {
public:
  Timer(char *name) : name(name) {
    QueryPerformanceCounter((LARGE_INTEGER*)&start);
  }
  ~Timer() {
    __int64 stop;
    QueryPerformanceCounter((LARGE_INTEGER*)&stop);
    printf("  %36s : % 4.2f s\n", name.c_str(), (stop - start)/double(freq));
  }
private:
  string const name;
  __int64 start;
};


template <typename Container, typename Index>
int binarySearch_indexed(Container sortedArray, Index first, Index last, int key) {
  while (first <= last) {
    Index mid = (first + last) / 2; // NOT safe if (first+last) is too big!
    if (key > sortedArray[mid])      first = mid + 1;
    else if (key < sortedArray[mid])  last = mid - 1; 
    else return mid;  
  }
  return 0; // Use "(Index)-1" in real code
}

int Dummy = -1;
int const *binarySearch_ptr(int const *first, int const *last, int key) {
  while (first <= last) {
    int const *mid = (int const *)(((unsigned __int64)first + (unsigned __int64)last) / 2);  
    if (key > *mid)      first = mid + 1;
    else if (key < *mid)  last = mid - 1; 
    else return mid;  
  }
  return &Dummy; // no NULL checks: don't do this for real
}

void timeFillWithAlloc() {
  printf("Counting memory (de)allocation...\n");
  { 
    Timer tt("memset (for reference)");
    int *data = (int*)malloc(N*sizeof(int));
    for (int it=0; it<nIter; it++) memset(data, 0, N*sizeof(int));
    free(data);
  }
  { 
    Timer tt("fill malloc-ed raw array with []");
    int *data = (int*)malloc(N*sizeof(int));
    for (int it=0; it<nIter; it++) for (size_t i=0; i<N; i++) data[i] = (int)i;
    free(data);
  }
  { 
    Timer tt("fill malloc-ed raw array with ptr");
    int *data = (int*)malloc(N*sizeof(int));
    for (int it=0; it<nIter; it++) {
    int *d = data;
    for (size_t i=0; i<N; i++) *d++ = (int)i;
    }
    free(data);
  }
  { 
    Timer tt("fill new-ed raw array with []");
    int *data = new int[N];
    for (int it=0; it<nIter; it++) for (size_t i=0; i<N; i++) data[i] = (int)i;
    delete [] data;
  }
  { 
    Timer tt("fill new-ed raw array with ptr");
    int *data = new int[N];
    for (int it=0; it<nIter; it++) {
    int *d = data;
    for (size_t i=0; i<N; i++) *d++ = (int)i;
    }
    delete [] data;
  }
  { 
    Timer tt("fill vector as array");
    vector<int> data(N); 
    for (int it=0; it<nIter; it++) {
      int *d = &data[0]; 
    for (size_t i=0; i<N; i++) *d++ = (int)i;
    }
  }
  { 
    Timer tt("fill vector");
    vector<int> data(N); 
    for (int it=0; it<nIter; it++) for (size_t i=0; i<N; i++) data[i] = (int)i;
  }
  printf("\n");
}

void timeFillNoAlloc() {
  printf("NOT counting memory (de)allocation...\n");

  { 
    int *data = (int*)malloc(N*sizeof(int));
    {
      Timer tt("memset (for reference)");
      for (int it=0; it<nIter; it++) memset(data, 0, N*sizeof(int));
    }
    free(data);
  }
  { 
    int *data = (int*)malloc(N*sizeof(int));
    {
      Timer tt("fill malloc-ed raw array with []");
      for (int it=0; it<nIter; it++) for (size_t i=0; i<N; i++) data[i] = (int)i;
    }
    free(data);
  }
  { 
    int *data = (int*)malloc(N*sizeof(int));
    {
      Timer tt("fill malloc-ed raw array with ptr");
      for (int it=0; it<nIter; it++) {
        int *d = data;
        for (size_t i=0; i<N; i++) *d++ = (int)i;
      }
    }
    free(data);
  }
  { 
    int *data = new int[N];
    {
      Timer tt("fill new-ed raw array with []");
      for (int it=0; it<nIter; it++) for (size_t i=0; i<N; i++) data[i] = (int)i;
    }
    delete [] data;
  }
  { 
    int *data = new int[N];
    {
      Timer tt("fill new-ed raw array with ptr");
      for (int it=0; it<nIter; it++) {
        int *d = data;
        for (size_t i=0; i<N; i++) *d++ = (int)i;
      }
    }
    delete [] data;
  }
  { 
    vector<int> data(N); 
    {
      Timer tt("fill vector as array");
      for (int it=0; it<nIter; it++) {
        int *d = &data[0]; 
        for (size_t i=0; i<N; i++) *d++ = (int)i;
      }
    }
  }
  { 
    vector<int> data(N); 
    {
      Timer tt("fill vector");
      for (int it=0; it<nIter; it++) for (size_t i=0; i<N; i++) data[i] = (int)i;
    }
  }
  printf("\n");
}

void timeBinarySearch() {
  printf("Binary search...\n");
  vector<int> data(N); 
  {
    Timer tt("fill vector (for reference)");
    for (size_t i=0; i<N; i++) data[i] = (int)i;
  }

  {
    Timer tt("array with ptr math");
    int sum = 0;
    for (int i=-1000000; i<1000000; i++) {
      sum += *binarySearch_ptr(&data[0], &data[0]+data.size(), i);
    }
  }
  {
    Timer tt("array with int index");
    int sum = 0;
    for (int i=-1000000; i<1000000; i++) {
      sum += data[binarySearch_indexed<int const *, int>(
        &data[0], 0, (int)data.size(), -1)];
    }
  }
  {
    Timer tt("array with ptrdiff_t index");
    int sum = 0;
    for (int i=-1000000; i<1000000; i++) {
      sum += data[binarySearch_indexed<int const *, ptrdiff_t>(
        &data[0], 0, (ptrdiff_t)data.size(), -1)];
    }
  }
  {
    Timer tt("vector with int index");
    int sum = 0;
    for (int i=-1000000; i<1000000; i++) {
      sum += data[binarySearch_indexed<vector<int> const &, int>(
        data, 0, (int)data.size(), -1)];
    }
  }
  {
    Timer tt("vector with ptrdiff_t index");
    int sum = 0;
    for (int i=-1000000; i<1000000; i++) {
      sum += data[binarySearch_indexed<vector<int> const &, ptrdiff_t>(
        data, 0, (ptrdiff_t)data.size(), -1)];
    }
  }

  printf("\n");
}

int main(int argc, char **argv)
{
  QueryPerformanceFrequency((LARGE_INTEGER*)&freq);

  timeBinarySearch();
  timeFillWithAlloc();
  timeFillNoAlloc();

  return 0;
}
6
ответ дан 3 December 2019 в 01:02
поделиться

Я работаю над общей библиотекой, которой нужен доступ к структурированным данным. Эти данные известны во время компиляции, таким образом, они используют ограниченные по объему файлом постоянные массивы POD (простые данные) структуры для содержания данных.

Это заставляет компилятор и компоновщика помещать большинство данных в раздел только для чтения с двумя преимуществами:

  • Это может быть отображено в каталог памяти от диска, не выполняя специального кода инициализации.
  • Это может быть совместно использовано процессами.

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

Если бы я использовал вектор и строковые объекты для этого, то компилятор сгенерировал бы намного больше кода инициализации, который выполнится каждый раз, когда моя общая библиотека загружается. Постоянные данные были бы выделены на "куче", таким образом, это не будет совместно используемо между процессами.

Если бы я считал данные в из файла на диске, то я должен был бы иметь дело с проверкой, что формат данных, вместо того, чтобы иметь компилятор C++ делают это для меня. Я также должен был бы управлять временем жизни данных в кодовой базе, которая имела эти глобальные данные, "испеченные в" их с начала.

1
ответ дан 3 December 2019 в 01:02
поделиться
Другие вопросы по тегам:

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