Scenarios
#include <chrono> #include <cstdio> #include <fstream> #include <iostream> #include <print> #include <string> #include <string_view> int main() { using namespace std::chrono; // -------------- C style (std::printf / std::fprintf) ---------- { auto start = high_resolution_clock::now(); const char* msg = "message content"; std::FILE* fp = fopen("file_c.txt", "w"); for (uint32_t i = 0; i < 100000; ++i) { auto now = system_clock::now(); std::time_t time = system_clock::to_time_t(now); std::tm local = *std::localtime(&time); std::fprintf(fp, "%04d-%02d-%02dT%02d:%02d:%02d %s\n", local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec, msg); // std::printf for stdout } std::fflush(fp); std::fclose(fp); auto end = high_resolution_clock::now(); std::println("{:<20}{:>10}ns", std::string{"C-style took:"}, duration_cast<nanoseconds>(end - start).count()); } // -------------- C++ style (std::cout / std::ofstream) --------- { auto start = high_resolution_clock::now(); std::string msg = "message content"; std::ofstream ofs("file_cpp_old.txt"); for (uint32_t i = 0; i < 100000; ++i) { auto now = system_clock::now(); std::time_t time = system_clock::to_time_t(now); std::tm local = *std::localtime(&time); ofs << std::setfill('0') << std::setw(4) << (local.tm_year + 1900) << "-" << std::setw(2) << (local.tm_mon + 1) << "-" << std::setw(2) << local.tm_mday << "T" << std::setw(2) << local.tm_hour << ":" << std::setw(2) << local.tm_min << ":" << std::setw(2) << local.tm_sec << " " << msg << "\n"; // std::cout for stdout } ofs.flush(); ofs.close(); auto end = high_resolution_clock::now(); std::println("{:<20}{:>10}ns", std::string{"Old C++-style took:"}, duration_cast<nanoseconds>(end - start).count()); } // -------------- C++ style (std::print / std::print) ----------- { auto start = high_resolution_clock::now(); std::string_view msg = "message content"; std::FILE* fp = std::fopen("file_c++_new.txt", "w"); for (uint32_t i = 0; i < 100000; ++i) { auto now = system_clock::now(); std::time_t time = system_clock::to_time_t(now); std::tm local = *std::localtime(&time); std::print(fp, "{:04}-{:02}-{:02}T{:02}:{:02}:{:02} {}\n", local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec, msg); // std::print for stdout } std::fflush(fp); std::fclose(fp); auto end = high_resolution_clock::now(); std::println("{:<20}{:>10}ns", std::string{"New C++-style took:"}, duration_cast<nanoseconds>(end - start).count()); } return 0; }
% uname -a Darwin FMXK77H3WK 24.6.0 Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:55 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6031 arm64 % g++ --version Apple clang version 17.0.0 (clang-1700.0.13.5) Target: arm64-apple-darwin24.6.0 % g++ main.cpp -O3 --std=c++23 % ./a.out C-style took: 48350334ns Old C++-style took: 54821291ns New C++-style took: 84056042ns
Comparison
Aspect | C-style | C++-style (< C++23) | C++-style (>= C++23) |
---|---|---|---|
Type safety | Not type-safe | Type-safe | Strong type-safety |
Verbosity | Low | High (lots of “>> “) |
Very low |
Performance * | Best | Good | Worst |
* Depends a lot on the use case. I will stick with the result of the test. Lots of writes into a file.