2015-01-27 3 views
-1

В C++, после кода ниже:Вывести список целых значений одновременно с помощью динамического массива указателя?

char *p = new char(); 
    *p = 'a'; 
    *(p+1)= 'b'; 
    *(p+2) ='\0'; 
    cout<<p<<endl; 

мы можем получить выходной результат: аб

Когда я хочу, чтобы написать такой код:

int *p = new int(); 
    *p = 1; 
    *(p+1)= 2; 
    cout<<p<<endl; 

Это дает результат , но не 12 или что-то начинаться с 12

Вопрос в том, почему результат меняется не так, если он меняет его на char? Как реализовать цель, которая выводит список значений с помощью динамического массива указателя?

+0

Неопределенное поведение очевидно (и может привести к путешествию во времени) – quantdev

+0

@quantdev Вы правы, но как я могу вывести все эффективные целочисленные значения в массиве без использования цикла? – SimaGuanxing

+0

@JoeWang - это совсем другой вопрос. Но начните, посмотрев на ответ Барри о том, как безопасно распределить массив int (и если вы знаете размер раньше времени, оставайтесь в стороне от 'new int [3]' в первую очередь ... просто используйте 'int intsToOutput [3]; '). –

ответ

2

Это потому, что char * - это немного особый случай.

В дни C char * был единственным типом, с которым нам действительно приходилось иметь дело со строками. C++ упрощает взаимодействие с устаревшим кодом, предоставляя потоковые операторы, которые обрабатывают значения char * специально, путем потоковой передачи каждого символа до тех пор, пока не встретится нулевой символ ('\0').

Когда вы обмениваетесь p, когда это int *, нет специального случая - вы просто получите отображаемое значение необработанного указателя.

Если вы хотите одну гильзу, чтобы отобразить элементы в стандартном контейнере, вы можете комбинировать std::copy() с std::ostream_iterator:

std::copy(std::begin(some_array), 
      std::end(some_array), 
      std::ostream_iterator<int>(std::cout)); 

Поскольку ваш массив выделяется в куче и хранится в указателе, std::begin() и std::end() не сработает для вас; Вы должны будете предоставить конечному итератор вручную: (. See a demo)

std::copy(p, p + 2, std::ostream_iterator<int>(std::cout)); 


Но обратите внимание, что оба образца кода в вашем вопросе не определено поведение, потому что вы выделить единый объект типа char или int, а затем попробуйте назначить за пределами. Вы записываете в память, которую вы не выделили. Не делайте этого.

Чтобы исправить свои дела, вам нужно выделить достаточно места для объектов, которые вы собираетесь хранить:

// Case one 
char *p = new char[3]; 

// Case two 
int *p = new int[2]; 

И, конечно же, не забудьте delete[] p в обоих случаях - или вы могли бы просто используйте std::string в первом случае и std::vector<int> во втором.

2

Ok, в первую очередь, это небезопасно:

*(p+1)= 'b'; 

Вы только выделили один байт, и теперь вы топать на память вы не владеете - что неопределенное поведение.Если вы хотите выделить 3 байта, сделайте это:

char* p = new char[3]; 

Во-вторых, это:

int* pi = new int; 
cout << pi << endl; 

Напечатает адрес указателя. char* является особенным в том, что cout фактически напечатает строку стиля C, на которую указывают, но для других типов - вы просто получите адрес.

Если вы хотите напечатать 12, вы должны разыменования указателя:

Если вы хотите вывести 1 и 2, по отдельности, вам нужен массив:

int* pi = new int[2]; 
pi[0] = 1; 
pi[1] = 2; 
cout << pi[0] << ", " << pi[1] << endl; 

Обратите внимание, что , опять же, *(p + 1) = 2 в вашем коде топает память, которой у вас нет.

+0

Спасибо. Итак, если я назначу 50 значений целочисленному массиву и хочу вывести все из них, у меня нет выбора, кроме использования цикла? – SimaGuanxing

+0

@JoeWang Нет, вы можете использовать 'std :: copy()' в соответствии с моим ответом. – cdhowie

Смежные вопросы