Почему вывод массива String выводит адрес?

210
08 января 2018, 10:46

Либо я криворукий либо я чего-то не понимаю)

Перезапуск проги лишь меняет адрес массива

Код

#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
int main() {
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    string classmates[3] = { "Козлов", "Иванов", "Сидоров" };
    cout << classmates << endl; //Вывожу весь массив, а выводится адрес?;
    cout << classmates[0] << endl; //Вывожу микрочелика
    cin.get();
}

Первый вывод

0040FE2C
Козлов

Второй вывод

004FFA1C
Козлов

и т.п.

Если допустим вывести весь массив символов ТО ОН ВЫВОДИТ ВЕСЬ МАССИВ СИМВОЛОВ. Объясните мне почему так происходит и можно ли исправить эту ошибку? Ну или хотя бы как-то обойти, а то не удобно как-то поочередно все строчки выводить

Answer 1

Потому что просто classmates низводится при передаче в функцию вывода (operator<<) до обычного указателя на первый элемент массива, и выводится как указатель - поскольку не является указателем на char.

В массиве лежат три объекта типа string, каждый из которых где-то внутри содержит указатель на реальную строку с фамилией... И как вы предлагаете выводить их все три? Если обратиться к ним нужно через 2 уровня косвенности? Они же лежат в совершенно разных местах памяти...

Да и что вы хотите получить?

КозловИвановСидоров

?

Нет, конечно, если вы считаете, что

for(auto s: classmates) cout << s << endl;

неудобно - можно воспользоваться стандартными алгоритмами и итераторами:

copy(begin(classmates),end(classmates),ostream_iterator<string>(cout,"\n"));
Answer 2

classmates - это массив. operator<< в ostream для массива не перегружен. Но массив без труда преобразуется в указатель, а operator<< перегружен для указателей, поэтому будет срабатывать перегрузка для указателя. При передаче operator<< указателя, он выводит значение указателя, т.е. адрес (для указателей на char будет выводить C-строку, но у нас не char).

Можно определить свой operator<<, чтобы выводить массивы:

template<std::size_t N>
std::ostream &operator<< (std::ostream &stream, const std::string (&arr)[N]) 
{
    for (auto &str: arr) {
        stream << str << '\n';
    }
    return stream;
}

Теперь при выводе массива будет выведена каждая строка отдельно.

#include <iostream>
#include <string>

template<std::size_t N>
std::ostream &operator<< (std::ostream &stream, const std::string (&arr)[N]) 
{
    for (auto &str: arr) {
        stream << str << '\n';
    }
    return stream;
}

int main()
{
    std::string classmates[3] = { "Козлов", "Иванов", "Сидоров" };
    std::cout << classmates << std::endl;
}

http://rextester.com/SSFBE17244

READ ALSO
Рисование круга внутри прямоугольника

Рисование круга внутри прямоугольника

Здравствуйте! Такая проблема, в дочернем классе неправильно подсчитывает площадь между прямоугольником и кругом`

232
Пролаги при старте программы из-за сети (qt)

Пролаги при старте программы из-за сети (qt)

При старте приложения в 80% случаев происходит лаг на 5-10 секунд если в приложении используется сеть (QNetworkAccessManager)

201
Нужен ли delete[] при использовании new c умным указателем типа auto

Нужен ли delete[] при использовании new c умным указателем типа auto

Вопрос касается C++11, использования auto в подобной структуре:

218