переопределение `istream operator››` по сравнению с использованием `sscanf`

Скажем, я хотел инициализировать std::vector объектов, например.

class Person { int ID; string name; ...}

из файла, который содержит строку для каждого объекта. Один путь состоит в том, чтобы переопределить operator>> и просто std::cin>>temp_person, другой, который я предпочитал, заключается в использовании sscanf("%...", &...) набора временных примитивных типов и просто .emplace_back(Person(temp_primitives...).

Какой способ обеспечивает самое быстрое время выполнения без учета объема памяти? Есть ли смысл mmap()ировать весь файл?


person Alex Petrosyan    schedule 08.08.2018    source источник
comment
Какой способ обеспечивает самое быстрое время выполнения без учета объема памяти? sscanf/fscanf, возможно, немного быстрее, но это может быть несущественно. Попробуйте и узнайте разницу.   -  person R Sahu    schedule 09.08.2018
comment
Какой способ обеспечивает самое быстрое выполнение без учета объема памяти? — профилируйте код и узнайте сами   -  person Remy Lebeau    schedule 09.08.2018
comment
Поскольку вы спрашивали о производительности mmap, см. мои ответы: улучшает ли mmap скорость чтения файлов"> stackoverflow.com/questions/37172740/ и многое другое: stackoverflow.com/questions/33616284/   -  person Craig Estey    schedule 09.08.2018
comment
Перегрузка operator>> во многом определяет синтаксис ее вызова. Если вы хотите реализовать это с помощью scanf, это довольно просто сделать. Другими словами, на самом деле это не ситуация «или-или». Вы можете сделать один или оба, как считаете нужным.   -  person Jerry Coffin    schedule 09.08.2018
comment
sscanf не имеет спецификаторов формата для std::string.   -  person Thomas Matthews    schedule 09.08.2018
comment
Вы можете использовать std::cin и >>, не перегружая оператор >>. Просто прочитайте временный объект и поместите его в вектор, как вы делаете с sscanf. С тем же успехом можно придерживаться ввода-вывода С++, если вам не нужно использовать ввод-вывод C.   -  person BessieTheCookie    schedule 09.08.2018
comment
Примечание. Если вы используете std::cin, а не файл. Не забудьте отсоединить буфер C++ от буфера C. Это улучшит производительность. std::ios::sync_with_stdio(false);   -  person Martin York    schedule 09.08.2018
comment
@MartinYork, к сожалению, мне нужно смешивать C/C++ io, в противном случае это хороший совет.   -  person Alex Petrosyan    schedule 09.08.2018
comment
@AlexPetrosyan Я сомневаюсь в необходимости. Возможно, у вас есть код C, смешанный с вашим C++. Но нужда — это сильно сказано. Вы просто не хотите тратить усилия на его рефакторинг. Что может быть правильным выбором. Но смешивая эти совершенно разные языки, вы не получите всей мощи C++. Выберите один язык, это упростит работу в долгосрочной перспективе.   -  person Martin York    schedule 09.08.2018
comment
@MartinYork, я понимаю, что вы имеете в виду, но иногда вы просто не можете реорганизовать код, например. когда вы используете внешнюю библиотеку, и вам нельзя ее трогать (мой случай).   -  person Alex Petrosyan    schedule 09.08.2018


Ответы (1)


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

Я бы предпочел маршрут operator>>, потому что это позволило бы мне использовать идиому итератора ввода C++:

std::istream_iterator<Person> eos;
std::istream_iterator<Person> iit(inputFile);
std::copy(iit, eos, std::back_inserter(person_vector));

или даже

std::vector<Person>   person_vector(
    std::istream_iterator<Person>(inputFile)
,   std::istream_iterator<Person>()
);
person Sergey Kalinichenko    schedule 08.08.2018
comment
Ударь меня. :-). Но вы также можете использовать конструктор std::vector<Person>, который принимает два итератора: std::vector<Person> person_vector(iit, eos); - person Martin York; 09.08.2018
comment
@MartinYork Большое спасибо, это имеет смысл! - person Sergey Kalinichenko; 09.08.2018
comment
@AlexPetrosyan Конечно, std::istreambuf_iterator<Person> тоже должно работать. Однако я не уверен, какие преимущества вы получите, работая на необработанном уровне персонажа. - person Sergey Kalinichenko; 09.08.2018
comment
@dasblinkenlight, я думаю, что это точный вариант использования буферизованного ввода-вывода. В Java bufferedReader при использовании для чтения объектов из стандартного ввода (ов) не будет создавать временные объекты для присваивания символу за символом, а скорее объект за объектом. В моем случае это приводит к скачку производительности, поэтому я думаю, что это того стоит. - person Alex Petrosyan; 09.08.2018
comment
@AlexPetrosyan В C ++ реализация сильно отличается, поэтому необработанные символы означают что-то другое. См. этот ответ для очень подробного объяснения того, что отличается (спойлер: не так много). - person Sergey Kalinichenko; 09.08.2018