Примечание: Я написал этот ответ в предположении, что T
в вашем вопросе представляет некоторый фактический тип данных - я выбрал int
в моих примерах ниже.
Background: Я пытался передать указатель const в функцию. [...] Я должен рассмотреть случаи, когда пропускается локальный указатель и в котором проходит временное (например, от возврата вызова функции)
Вы не сказали, что вы подразумеваете под "const pointer". Сначала я предполагаю, что вы имеете в виду указатель, который сам по себе является постоянным (т. Е. Адрес, на который он указывает, не может быть изменен).
По вашему описанию, есть в основном два способа получить такой указатель:
// Case 1 (what you call a local pointer -- this should be inside some
// function body):
int *const p = 0;
// Case 2, a function that returns a pointer; this is your rvalue case
// in contexts where f() is called and its return value used as a temporary:
int *f()
{ return 0; }
// Note: The temporary returned by this function isn't, strictly speaking,
// constant. It could be modified as long as it is alive. But from
// your description I take it that you have no intentions of doing so
// and/or regard temporaries as generally constant.
Теперь вы можете определить функцию, которая принимает эти два случая следующим образом:
void g(int *const &arg)
{ }
Вы можете примените это как g(p);
к постоянному локальному указателю, такому как p
, определенному ранее, а также к временному g(f());
.(Вы можете, в-третьих, применить его к неконстантного местного указателя, а также, потому что происходит от неконстантного Lvalue к сопзЬ Lvalue никогда не является проблемой.)
Эта функция g
имеет аргумент функции arg
который определяется как постоянная ссылка на значение int
. Он может привязываться к постоянному (или действительно непостоянному) локальному указателю (например, p
), а также к временному, поскольку константные ссылки lvalue, в отличие от ссылок на константу lvalue, могут это сделать.
Примечание: Непонятно, почему в этом случае вам нужно, чтобы аргумент функции был ссылкой. Вы можете просто объявить void g(int *const arg)
(без амперсанда) и без справки. Причины включают: а) вы все равно не можете его изменить; б) Во всех реалиях реального мира эта ссылка займет столько же (или как мало) место, что и сам указатель, поэтому нет смысла избегать копирования.
В любом случае. Если вы хотите, вы можете также определить вторую версию g
специально для ссылок RValue:
void g(int *&& arg)
{ }
Это может только применяться к временным, не к локальному указателю, так как аргумент функции определяется как RValue ссылка, которая может привязываться к временным, но не к lvalues.
Однако, если указателем «const const» вы на самом деле означаете указатель-на-const, то есть указатель, который может быть изменен на разные адреса, но не имеет права изменять значение, хранящееся на этих адресах, объявления немного отличаются. Ключевое слово const
должно быть затем поставить перед звездочкой, и для большей наглядности лучше перед спецификатором типа int
:
// Declare local pointer-to-const:
const int *p = 0;
// Function that returns a pointer-to-const:
const int *f()
{ return 0; }
Функция, которая может принять эти два будут затем быть объявлен как:
void g(const int *const &arg)
{ }
первый const
означает, что мы говорим о указателях-константах, а второй const
гарантирует, что мы имеем константу lvalue-reference, которая может связываться как с rvalues, так и с lvalues. Обратите внимание, что эта функция не может изменить то, что указывает arg
, потому что arg
объявлен как константная ссылка lvalue. В случае, когда arg
привязывается к временному, это, вероятно, то, что мы хотим в любом случае (как указано выше). Но в случае, когда функция называется g(p);
, мы могли бы захотеть изменить локальный указатель p
с точностью до g
. Если вы хотите g
иметь эту силу, необходимо определить две версии этого:
void g(const int *&& arg)
{ /* Can bind to temporaries, but not modify them. */ }
void g(const int *& arg)
{ /* Can bind to local variables and modify what they point at */ }
Примечание 1: Ваша первоначальная декларация const int *const &const
бесполезно (и даже не принято НКУ). Это означало бы «постоянную ссылку на постоянный указатель на константу int», но поскольку ссылка на константный указатель сама по себе не является константой-ссылкой, окончательный const
является излишним (и не предусмотренным стандартом).
Примечание 2: Универсальные ссылки - это не то же самое, что ссылки на rvalue. Универсальные ссылки объявляются как T &&arg
, где T
является параметром шаблона.В зависимости от того, что T
относится к каждому экземпляру шаблона, это может быть ссылка на lvalue или ссылка на rvalue, следовательно, ее «универсальный» символ. В любом случае, это не имеет никакого отношения к вашему варианту использования, поскольку вы имеете дело с указателями T *
(даже если предположить, что T
является параметром шаблона).
http://stackoverflow.com/questions/17005423/c-rvalue-reference-and-const-qualifier может помочь, но ваш вопрос немного запутан. Кажется, вы смешиваете свободно указатель const и указатель на const. Если вам не нужно идеально переходить или перемещаться, rvalue refs не очень полезно. – Mat
«Универсальные ссылки» применяются только при использовании ссылки с шаблоном. – Rastaban