Ответ
Для атомарного создания файла только при его отсутствии (чтобы избежать состояния гонки между проверкой exists и созданием) необходимо использовать низкоуровневые системные вызовы или флаги файловой системы.
1. Использование системного вызова open() с флагами O_CREAT | O_EXCL (POSIX, наиболее надёжно):
Этот метод атомарен даже в многопоточной и многопроцессной среде.
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <iostream>
int fd = open("myfile.txt", O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd == -1) {
if (errno == EEXIST) {
std::cout << "Файл уже существует.n";
} else {
perror("open failed");
}
} else {
std::cout << "Файл успешно создан.n";
close(fd); // Не забываем закрыть дескриптор
}
2. Использование std::ofstream с флагами (C++17, но не полностью атомарно на всех файловых системах):
#include <fstream>
#include <iostream>
std::ofstream file("myfile.txt", std::ios::out | std::ios::app); // app не перезаписывает
// Но это не гарантирует, что файл не существовал до этого.
// Более точный, но всё же не атомарный способ (C++17):
#include <filesystem>
namespace fs = std::filesystem;
if (!fs::exists("myfile.txt")) {
std::ofstream new_file("myfile.txt");
}
// !ВНИМАНИЕ: Между проверкой exists и созданием файла другой процесс может успеть его создать.
Вывод: Для гарантированно атомарного создания в конкурентной среде следует использовать системный вызов open() с флагами O_CREAT | O_EXCL.