можна досягти моделі власності Руста за допомогою загальної оболонки C ++?


15

Переглядаючи цю статтю про безпеку паралельних ресурсів Руста:

http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html

Мені було цікаво, скільки цих ідей можна досягти за C ++ 11 (або новіших). Зокрема, чи можу я створити клас власника, який передає право власності на будь-який метод, до якого він може бути переданий? Здається, що у C ++ є стільки способів передачі змінних, що це було б неможливо, але, можливо, я міг би поставити деякі обмеження щодо класу чи шаблону, щоб забезпечити виконання якогось коду шаблону при кожному проходженні методу?


Деякі цитати з посилання покращать це питання
Мартін Ба

2
@delnan (Безпечний) Іржа гарантує, що ви ніколи не матимете більше одного змінного посилання на щось за один раз і що у вас ніколи не має змінених посилань на речі, на які ви також маєте посилання лише для читання. Він також має деякі обмеження щодо передачі даних між потоками. Вони разом запобігають значному класу помилок, пов’язаних з нанизуванням, і полегшують міркування про стан об'єктів, навіть у єдиному потоковому коді.
CodesInChaos

3
Ви не думаєте, що можете виражати запозичення таким чином, щоб компілятор C ++ міг перевірити, тож вам доведеться вдатися до виконання часу виконання з відповідним хітом ефективності.
CodesInChaos

1
Чи не володіють сферами власності вже реалізовані смарт-покажчики в C ++ 11?
Акшат Махаджан

1
@JerryJeremiah Rust має широкий спектр посилань. Основні з них, &не вимагають використання будь-якої реклами. Якщо ви спробуєте знайти деякий &mutчас, у вас ще є інша посилання (на зміну чи ні) на той самий елемент, ви не зможете компілювати. RefCell<T>переміщує чек на час виконання, так що ви отримаєте паніку , якщо ви намагаєтеся .borrow_mut()що - то , що вже є активний .borrow()або .borrow_mut(). У Rust також є Rc<T>(спільне володіння вказівником) та його братів Weak<T>, але це стосується власності, а не змінності. Приклейте RefCell<T>всередину їх для змінності.
8bittree

Відповіді:


8

C ++ має три способи передачі параметрів функції: за значенням, за посиланням lvalue та за посиланням rvalue. З них передача за значенням створює право власності в тому сенсі, що викликана функція отримує власну копію, а передача посилання на значення rvalue вказує на те, що значення може бути спожито, тобто більше не буде використовуватися абонентом. Проходження посилання на значення lvalue означає, що об'єкт тимчасово запозичений у абонента.

Однак вони, як правило, є "за домовленістю" і не завжди можуть перевіряти компілятор. І ви можете випадково перетворити посилання lvalue в посилання на rvalue, використовуючи std::move(). Конкретно, є три проблеми:

  • Посилання може переживати об'єкт, на який він посилається. Система життя Руста запобігає цьому.

  • У будь-який час може бути більше однієї змінної / неконтрольованої посилання. Перевірка позики Раста запобігає цьому.

  • Ви не можете відмовитись від посилань. Ви не можете побачити на сайті виклику, чи створює ця функція посилання на ваш об'єкт, не знаючи підпису викличеної функції. Тому ви не можете надійно запобігти посиланням, ні шляхом видалення будь-яких спеціальних методів своїх класів, ні шляхом аудиту сайту для викликів на відповідність деякому посібнику зі стилю "без посилань".

Проблема в житті полягає в основній безпеці пам'яті. Звичайно, незаконно використовувати посилання, коли термін дії посилання закінчився. Але дуже просто забути про час життя, коли ви зберігаєте посилання в об'єкті, зокрема, коли цей об'єкт переживає поточну область. Система типу C ++ не може цього пояснювати, оскільки вона взагалі не моделює життя об'єкта.

std::weak_ptrСмарт - покажчик робить власність кодування семантики , аналогічну просте посилання, але вимагає, щоб посилання об'єкт управляється через shared_ptr, тобто є лічильник посилань. Це не абстрагування з нульовою вартістю.

Хоча C ++ має систему const, вона не відстежує, чи може об'єкт бути модифікована, але відстежує, чи може об'єкт бути модифікований за допомогою цієї конкретної посилання . Це не дає достатніх гарантій для "безстрашної одночасності". Навпаки, Руст гарантує, що якщо є активна змінна посилання, яка є єдиною посиланням ("Я єдиний, хто може змінити цей об'єкт"), а якщо є незмінні посилання, то всі посилання на об'єкт не змінюються («Поки я можу читати з об’єкта, ніхто не може його змінити»).

У C ++ ви можете спокуситись захистити доступ до об'єкта за допомогою інтелектуального вказівника з мютекс. Але, як обговорено вище, як тільки ми маємо посилання, це може уникнути очікуваного терміну експлуатації. Тому такий розумний покажчик не може гарантувати, що це єдина точка доступу до керованого об'єкта. Така схема може фактично спрацювати на практиці, оскільки більшість програмістів не хочуть саботажу, але з точки зору типової системи це все ще є абсолютно невідомим.

Загальна проблема з розумними покажчиками полягає в тому, що вони є бібліотеками, що лежать на основі основної мови. Набір основних функцій мови дозволяє цим розумним покажчикам, наприклад, std::unique_ptrконструкторам потреб рухатися. Але вони не можуть виправити недоліки в основній мові. Здатність неявно створювати посилання під час виклику функції та мати звисаючі посилання разом означають, що основна мова C ++ не є голосною. Неможливість обмеження змінних посилань однією означає, що C ++ не може гарантувати безпеку проти гоночних умов з будь-яким видом одночасності.

Звичайно, багато в чому С ++ та Іржа схожіші, ніж вони не схожі, зокрема щодо їхніх понять про статично визначені життєві періоди. Але хоча можна записати правильні програми C ++ (за умови, що жоден із програмістів не помилиться), Rust гарантує коректність щодо обговорюваних властивостей.


Якщо проблема полягає в тому, що C ++ не відстежує право власності на основній мові, чи можна було б реалізувати цю функціональність за допомогою метапрограмування? Це означає, що ви створили новий клас розумних покажчиків, який би був безпечним для пам'яті шляхом (1), змушуючи його вказувати виключно на об'єкти, які використовують лише інтелектуальні покажчики того ж класу та (2) відстеження права власності через шаблони
Елліот Гороховський

2
@ElliotGorokhovsky Ні, оскільки шаблон не може вимкнути функції основної мови, такі як посилання. Розумний вказівник може ускладнити отримання посилання, але в цей момент ви боретеся з мовою - більшість стандартних функцій бібліотеки потребують посилань. Також неможливо перевірити термін служби посилання за допомогою шаблонів, оскільки мова не пропонує рефікованої концепції життя.
Амон

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.