Что именно должен PROTECT обернуть при назначении?

Я перечитал бит о сборке мусора в письме R расширений несколько раз и до сих пор не понимаю разницы между этими двумя обычаями:

SEXP var = PROTECT(allocVector(STRSXP, 100));

против

SEXP var;
PROTECT(var = allocVector(STRSXP, 100));

До сих пор у меня была худшая удача с первой, так как мой сеанс иногда с ней сработал (но я вижу, что это много используется как в реальном коде, так и в самом руководстве по интро). Может ли кто-нибудь объяснить разницу между этими двумя назначениями?

изменить

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

Ответ 1

Это строго эквивалентно. Это функция, называемая PROTECT (от https://svn.r-project.org/R/trunk/src/main/memory.c)

SEXP protect(SEXP s)
{
    if (R_PPStackTop >= R_PPStackSize)
    R_signal_protect_error();
    R_PPStack[R_PPStackTop++] = CHK(s);
    return s;
}

static R_INLINE SEXP CHK(SEXP x)
{
    /* **** NULL check because of R_CurrentExpr */
    if (x != NULL && TYPEOF(x) == FREESXP)
    error("unprotected object (%p) encountered (was %s)",
          x, sexptype2char(OLDTYPE(x)));
    return x;
}
#else
#define CHK(x) x
#endif

и from.include/Rinternals.h:

#define TYPEOF(x)   ((x)->sxpinfo.type)

Как вы можете видеть, аргумент указателя возвращается без изменений, так что

var = PROTECT(p)
PROTECT(var = p)

эквивалентны