Pre C++11 the code was legal. Since C++11 that is considered a narrow conversion (from double to int there is information loss) and is illegal.
What compiler and what version of compiler you use matters. Visual Studio, especially slightly older versions don't actually implement any standard in full. They implements bits of C++11, bits of C++14, bits of C++17. With the newest versions that could have possibly changed, I haven't followed it's evolution lately.
Really older versions of gcc default to gnu++98 which is C++98 with gnu extensions, while newer version default to gnu++11 and gnu++14. For your curiosity if you want to see it working in gcc use -std=c++98 and you will only get a warning.
In hindsight we have learned that allowing implicit conversions that can lose information (e.g. from floating point to integer, from long long to int) was not a good ideea. With C++11 this was taken into consideration. Making all such implicit conversions illegal was deemed to much of a breaking change. The introduction of list initialization offered a middle ground: disallow narrowing conversions only in a list initialization and recommend using list initialization as de facto way of initializing an object. The downside was that it was a breaking change for array initialization, but the benefits were weighted to be of more value.
int a = 2.4; // still allowed, but not recommended
int a(2.4); // still allowed, but not recommended
int a = {2.4}; // New way to initialize. Narrowing conversion, illegal
int a{2.4}; // New and recommended way to initialize. Narrowing conversion, illegal
You can read more about narrow conversions here: https://en.cppreference.com/w/cpp/language/list_initialization