Перегруженные параметры шаблона - почему этот пример является проблемой? - PullRequest
3 голосов
/ 02 ноября 2010

Я начал читать C ++ Templates - полное руководство Josuttis и Vandevoorde.И мой крошечный ум застрял.

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

template <typename T>
inline T const& max (T const& a, T const& b)
{
    return a < b ? b : a;
}

// maximum of two C-strings
inline char const* const& max( char const* a, char const* b)
{
    return std::strcmp(a, b) < 0 ? b : a;
}

template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
    return max( max(a,b), c);
}

Они говорят, что использование max аргумента с тремя аргументами является ошибкой -

const char * s1 = "fred";
const char * s2 = "anica";
const char * s3 = "lucas";
::max(s1, s2, s3); // ERROR

", потому что для C-строк max(a,b) создает новое временное локальное значение, которое может быть возвращенофункция по ссылке.Но я скомпилировал и запустил его просто отлично.

Может кто-нибудь объяснить, что автор говорит в этом примере?

Ответы [ 4 ]

3 голосов
/ 02 ноября 2010

Проблема в том, что перегрузка для «максимум двух C-строк» ​​принимает два аргумента по значению, но затем возвращает ссылку на один из них.Возвращение ссылки на локальную переменную - это Плохая идея (когда локальная переменная уничтожается, когда функция возвращается, ссылка не может использоваться, поэтому она бесполезна).

Вы можете исправить это, взяв оба из const char* s по константной ссылке:

char const* const& max( char const* const& a, char const* const& b)

Исходная версия, вероятно, компилируется, но если вы используете значение, возвращаемое при вызове max (что вы и делаете, так как вы используете результат max(a,b) когда вы вызываете max(max(a,b),c)), поведение не определено (потому что вы используете уничтоженный объект).

1 голос
/ 02 ноября 2010

Вы не взяли a и b по ссылке.Возвращение одного из них по ссылке означает, что вы возвращаете ссылку на параметр, который является локальной переменной в стеке.

0 голосов
/ 30 июня 2015

Вторая функция книги max, которая сравнивает две C-строки, фактически определяется как

inline char const* max( char const* a, char const* b)
{
    return std::strcmp(a, b) < 0 ? b : a;
}

Так что звонок max(a,b) внутри max(max(a,b),c) не является виновником. Это связано с тем, что max(max(a,b),c) разрешено перегрузкой до max( char const* a, char const* b), где a принимает возвращаемое значение max(a,b). Но эта функция возвращает значение , а 3-аргумент max возвращает ссылка ; следовательно ошибка.

0 голосов
/ 02 ноября 2010

Я не уверен, что они пытаются сказать, потому что я не вижу, как это создаст временную локальную переменную, но использование шаблонов с C-строками может дать сбой другими необычными способами, то есть различиями между массивами различной длины.Различия между массивом char и char * и т. д.

http://codeidol.com/cpp/cpp-templates/Tricky-Basics/Using-String-Literals-as-Arguments-for-Function-Templates/ служат хорошим справочным материалом для решения этих проблем.

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