2016-02-05 3 views
4

Согласно говорить Герб Саттер в CppCon 2015, shared_ptr должен быть признан недействительным после модификацииЗачем нужно менять общий указатель после изменения?

auto sv = make_shared<vector<int>>(100); 
shared_ptr<vector<int>>* sv2 = &sv; 
vector<int>* vec = &*sv; 
int* ptr = &(*sv)[0]; 
*ptr = 1 ; 

vec->push_back(2);  //A: modification 
*ptr = 5;     //Error: ptr was invalidated by "push_back" on line A 

ptr = &(*sv)[0]; 
(*sv2).reset();   //B: modification 
vec->push_back(6);   //Error: vec was invalidated by "reset" on line B 

Моего компилятора не ловит ни один из этих ошибок. Во всяком случае, мы используем интеллектуальные указатели для предотвращения утечки памяти. В чем причина подавления модификации shared_ptr? Во избежание сюрпризов? Если это так, не можем ли мы объявить его как const? С другой стороны, если многие операции с vector не могут быть применены из-за share_ptr, неужели это неудобно?


После прочтения комментариев, теперь я начинаю понимать, что он здесь делает. Модификация shared_ptr делает недействительными другие необработанные указатели, указывающие на нее.

Как указано в комментарии, push_back может перераспределить, что может привести к аннулированию ptr. Если он не перераспределяется, должно ли оставаться ptr? Если он перераспределит, не будет ли это проще и конструктивнее, если компилятор просто переведет всех своих приятелей на новую территорию, скажем, назначит эти исходные указатели новым адресом?

+0

Чтобы быть понятным, общий указатель не является недействительным; он говорит, что другие, не управляемые указатели на один и тот же ресурс недействительны. Я тоже не могу ответить. –

+1

Можете ли вы указать, где в видео он говорит это? – AndyG

+8

'vec-> push_back' может перераспределять, и в этом случае указатели на старое распределение становятся недействительными. Это относится к 'ptr' в примере A. Аналогичным образом, если вы сбросите' shared_ptr' и это единственный владелец вектора, тогда этот вектор будет уничтожен и указатели на (и в) этот вектор станут недействительными.Это пример 'vec' в примере B. – dyp

ответ

0

В большем контексте вещей Herb рекламировал Guidelines Support Library на CPPCon 2015 (он был не единственным).

Точка, которую он пытался сделать, заключалась в том, что существует код, который является совершенно законным в соответствии со стандартом, но со статическим анализом мы можем сказать, что это проблематично.

В приведенном здесь примере у нас есть shared_ptrvector, а затем необработанный указатель на этот указатель, а затем необработанный указатель на вектор, удерживаемый совместно используемым указателем, и даже необработанный указатель на элемент, удерживаемый внутри вектора, содержащегося в общем указателе.

И затем он сделал кучу вещей, которые приведут к неопределенному поведению. Вызовы были совершенно законными (сброс вызова на shared_ptr, а затем попытка выполнить операцию на vector), однако в более широком контексте вещей он утверждал, что компилятор должен сможет рассказать вам (через статический анализ), что вы сделали Bad Thing.

Таким образом, в видеоролике вы видите, что он делает эти плохие вещи, которые не компилирует современный компилятор, а затем демонстрирует, как компилятор (в данном случае Visual Studio 2015), пропитанный GSL , будет поймать их.

Разговор был одинаково политическим, поскольку он был информативным. Visual Studio использовалась, вероятно, потому, что Herb сам является сотрудником Microsoft. Это не обязательно плохо; широко распространено мнение, что Visual Studio - отличная среда разработки, и я думаю, что сообщение, которое нужно убрать, - это то, что Microsoft действительно привержена C++, несмотря на множество ходов в последние годы, которые продемонстрировали, возможно, более высокую приверженность C#, которая оставила C++ разработчиков как граждане второго сорта.

Смежные вопросы