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.