Что такое ODR (One Definition Rule) в C++?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Правило одного определения (One Definition Rule, ODR) требует, чтобы в программе каждая сущность (функция, переменная, класс, перечисление, шаблон и т.д.), имеющая внешнее связывание (external linkage) или не имеющая связывания (no linkage), была определена ровно один раз. Имеющие внутреннее связывание (internal linkage) или локальные переменные могут определяться в каждой единице преобразования (translation unit).
Особые случаи для ODR:
- Встраиваемые функции и переменные (inline functions and variables): Могут определяться в нескольких единицах преобразования, но все их определения должны быть идентичны с точки зрения токенов (token by token).
- Шаблоны (templates): Определения шаблонов (функций, классов, переменных, алиасов) могут присутствовать в нескольких единицах преобразования там, где они явно или неявно инстанцируются. Все такие определения должны быть идентичны.
- Типы с разным представлением (types with different representations): Нарушение ODR может привести к неопределенному поведению, если общая сущность (например, класс) определена по-разному в разных единицах преобразования.
Примеры ODR:
Нарушения ODR:
// file1.cpp
int global_var = 10;
// file2.cpp
int global_var = 20; // Нарушение ODR: повторное определение global_var
// file1.cpp
void print_message() {
std::cout << "Hello from file1." << std::endl;
}
// file2.cpp
void print_message() { // Нарушение ODR: повторное определение функции
std::cout << "Goodbye from file2." << std::endl;
}
Соответствие ODR:
// common.h
extern int external_var; // Объявление
// file1.cpp
#include "common.h"
int external_var = 5; // Определение
// file2.cpp
#include "common.h"
// Используется определение из file1.cpp
// header.h
inline void print_inline() {
std::cout << "This is inline." << std::endl;
}
// file1.cpp
#include "header.h"
// print_inline определена здесь
// file2.cpp
#include "header.h"
// print_inline определена здесь, но это разрешено для inline функций
Нарушение ODR часто приводит к ошибкам компоновки (linker errors) или, что хуже, к неопределенному поведению во время выполнения.