Вы можете использовать тот, который используется плагином jQuery Validation:
/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i
Это правило языка, известного как одно правило определения . Внутри программы каждый статический объект (если он используется) должен быть определен один раз и только один раз.
Определения классов обычно идут в файлах заголовков, включенных в несколько единиц перевода (т. Е. Из нескольких исходных файлов). Если объявление статического объекта в заголовке было определением, то вы бы получили несколько определений, по одному в каждом блоке, который включает заголовок, который нарушил бы правило. Таким образом, вместо этого это не определение, и вы должны предоставить только одно определение где-то еще.
В принципе, язык может делать то, что он делает с встроенными функциями, позволяя нескольким определениям быть объединены в единый. Но это не так, поэтому мы придерживаемся этого правила.
Речь идет не о части распределения памяти. Речь идет о том, чтобы иметь единую точку определения в связанной части компиляции. @Nick также указал на это.
Из веб-сайта Bjarne http://www.stroustrup.com/#in-class
A класс обычно объявляется в файле заголовка, и заголовочный файл обычно включается во многие единицы перевода. Однако, чтобы избежать сложных правил компоновщика, C ++ требует, чтобы каждый объект имел уникальное определение. Это правило будет нарушено, если C ++ допускает определение класса объектов в классе, которое должно храниться в памяти как объекты.
blockquote>
Начиная с C ++ 17 теперь вы можете определить статические элементы данных внутри класса. См. cppreference :
Элемент статических данных может быть объявлен как встроенный. Встроенный элемент статических данных может быть определен в определении класса и может указывать инициализатор. Для этого не требуется определение вне класса:
blockquote>struct X { inline static int n = 1; };