Const reference default-value

Возможный дубликат:
как инициализировать аргументы функции, которые являются классами со значением по умолчанию

#include <string>

void foo1(const std::string& s = std::string());

void foo2(std::string& s = std::string());

void foo3(const std::string s = std::string());

void foo4(std::string s = std::string());

error at foo2(): default argument for ‘std::string& s’ has type ‘std::string {aka std::basic_string<char>}’

Я понимаю точку компилятора, но я не понимаю, как это не относится к foo1().

Ответ 1

Вы не можете взять неконстантную ссылку на временную, например, как foo2.

Обратите внимание, что это не специальные параметры по умолчанию. Вы получаете ту же ошибку для функциональных переменных: http://ideone.com/g7Tf7L

#include <string>
using std::string;

#include <iostream>
using std::cout; using std::endl;

int main()
{
    string s1        = string("s1"); // OK, copy it
    const string& s2 = string("s2"); // OK, const reference to it
    string& s3       = string("s3"); // ERROR! non-const reference not allowed!

    cout
            << s1 << ", "
            << s2 << ", "
            << s3 << endl;
    return 0;
}

Когда вы ссылаетесь на ссылку const на временную, время жизни временного объекта распространяется на время жизни ссылки (§12.2, цитируемое из моей копии проекта С++ 11 n3337):

Есть два контекста, в которых временные объекты уничтожаются в другой точке, чем конец fullexpression.

...

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

  • Временная привязка к ссылочному элементу в конструкторе ctor-initializer (12.6.2) сохраняется до завершения конструктора.
  • Временная привязка к эталонному параметру в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.
  • Время жизни временной привязки к возвращаемому значению в операторе return функции (6.6.3) не продлевается; временное уничтожается в конце полного выражения в операторе return.
  • Временная привязка к ссылке в new-initializer (5.3.4) сохраняется до завершения полного выражения, содержащего новый-инициализатор.

Ответ 2

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

Ответ 3

Объявления foo3 и foo4 являются законными, поскольку аргумент этих функций не является ссылкой.

Объявление foo2 является незаконным, потому что вы не можете привязывать неконстантную ссылку на временную.

Итак, почему декларация foo1 законна? Это очень важный const классификатор, который делает это выражение законным.