C ++: Безопасно ли использовать функции вызывающих абонентов в функции? - PullRequest
2 голосов
/ 12 июля 2011

Я думаю, что лучше всего описать ситуацию на примере кода:

int MyFuncA()
{
    MyClass someInstance;
    //<Work with and fill someInstance...>

    MyFuncB( &someInstance )
}

int MyFuncB( MyClass* instance )
{
    //Do anything you could imagine with instance, *except*:
    //* Allowing references to it or any of it's data members to escape this function
    //* Freeing anything the class will free in it's destructor, including itself

    instance->DoThis();
    instance->ModifyThat();
}

А вот и мои простые вопросы:

  • Гарантируется ли приведенная выше концепция в соответствии со стандартами C и C ++ для правильной работы? Почему (нет)?
  • Считается ли это делать это, осторожно и осторожно, плохой практикой?

Ответы [ 5 ]

1 голос
/ 12 июля 2011

Другие ответили на основной вопрос: «Да, это законно». И в отсутствие большей архитектуры трудно назвать это хорошей или плохой практикой. Но я постараюсь развить философский подход к более широкому вопросу, который вы, похоже, задаете в отношении указателей, времени жизни объектов и ожиданий при вызовах функций ...

В языке C ++ нет встроенного способа передачи указателя на функцию и «принудительного применения», чтобы он не убирал ее после завершения вызова. А поскольку указатели C ++ по умолчанию являются « слабыми ссылками» , указанные объекты могут исчезнуть из-под кого-то, кому вы передадите его.

Но явно абстракции слабых указателей существуют, например, в Qt:

http://doc.qt.nokia.com/latest/qweakpointer.html

Они предназначены для особого кодирования «паранойи» получателю, что объект, за который он держится, может исчезнуть из-под него. Любой разыменовывающий один вид понимает, что что-то не так, и они должны принять надлежащие меры предосторожности в соответствии с контрактом на разработку.

Кроме того, существуют абстракции, такие как разделяемый указатель, которые сигнализируют получателю о другом понимании. Передав им один из них, вы получаете право сохранять объект живым так долго, как захотите, что дает вам что-то вроде сборки мусора:

http://doc.qt.nokia.com/4.7-snapshot/qsharedpointer.html

Это только некоторые варианты. Но в самом общем смысле, если вы придумаете любой интересный инвариант для времени жизни вашего объекта ... подумайте о том, чтобы не передавать необработанные указатели. Вместо этого передайте некоторый класс обтекания указателя, который воплощает и документирует правила «игры» в вашей архитектуре.

(Одна из основных причин использования C ++ вместо других языков - это множество инструментов, которые вы должны делать, например, без лишних затрат!)

1 голос
/ 12 июля 2011

Я не вижу проблем в том, чтобы фактически использовать указатель, который вы передали для вызова функций объекта.Пока вы вызываете публичные методы MyClass, все остается в силе C / C ++.

Фактический экземпляр, созданный вами в начале MyFuncA(), будет уничтожен в конце MyFuncA(), и выгарантируется, что экземпляр останется действительным в течение всего выполнения MyFuncB(), поскольку someInstance все еще действует в области действия MyFuncA().

1 голос
/ 12 июля 2011

Да, это будет работать.Не имеет значения, находится ли указатель, который вы передаете в MyFuncB, в стеке или в куче (в данном конкретном случае).

Что касается части с плохой практикой, вы, вероятно, можете утверждать оба пути.В целом, я думаю, что это плохо, потому что если по какой-либо причине какой-либо объект, который живет за пределами MyFuncA, получит ссылку на объект, то впоследствии он умрет ужасной смертью и иногда будет очень трудно отслеживать ошибки.Это зависит от степени использования объекта в MyFuncB.Особенно, когда начинается еще один третий класс, он может запутаться.

1 голос
/ 12 июля 2011

Гарантируется ли вышеуказанная концепция в соответствии со стандартами C и C ++, чтобы она работала так, как ожидалось? Почему (нет)?

Да, все будет работать как положено. someInstance доступно в объеме MyFuncA. Вызов MyFuncB находится в этой области.

Считается ли это делать это, осторожно и осторожно, плохой практикой?

Не понимаю, почему.

0 голосов
/ 12 июля 2011

Я не думаю, что должна быть какая-то проблема с этим запретом, как вы говорите, чем-то, что освобождает объект или иным образом разрушает его состояние. Я думаю, что любые неожиданные вещи не будут иметь ничего общего с использованием класса таким образом. (конечно, ничего в жизни не гарантировано, но классы предназначены для передачи и обработки, будь то локальная переменная или иное, я не считаю, что это актуально.)

единственное, что вы не смогли бы сделать, это сохранить ссылку на класс после того, как он выйдет из области видимости, когда MyFuncA () вернется, но это просто природа правил области видимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...