Я только что обнаружил, насколько легко изменять объекты const без какой-либо черной магии const_cast
. Рассмотрим:
#include <iostream>
class Test {
public:
Test(int v)
:m_val{ v },
m_ptr{ &m_val }
{}
int get() const { return m_val; }
void set(int v) const { *m_ptr = v; }
private:
int m_val;
int* m_ptr;
};
int main()
{
const Test t{ 10 };
std::cout << t.get() << '\n';
t.set(0);
std::cout << t.get() << '\n';
return 0;
}
В последних версиях Clang, GCC и MSVC не отображаются предупреждения и производятся ожидаемые результаты:
10 0
Является ли это четко определенным поведением в соответствии с текущим стандартом? Если он undefined что, если m_val
имел тип std::aligned_storage_t<sizeof(int), alignof(int)>
и конструктор new
'ed int
в нем? Я считаю, что это довольно распространенный случай, когда речь идет о оптимизации небольших буферов.
Edit
Спасибо, кажется, это просто еще один способ застрелить себя ногой. Что беспокоит, кажется, что это:
struct Test2 {
int i;
void operator()() { ++i; }
};
const std::function<void()> f{ Test2{ 10 } };
f();
также является undefined, когда реализация решает сохранить объект Test2
внутри f
(и что случай в libС++ и в Visual Studio)