Сначала я неправильно оценил ваш вопрос, потому что неправильно прочитал ваш код. Собственно, в вашем коде char const*& func(char const*& a, char const*& b,char const*& c)
никогда не вызывается;)
Эта часть вашего кода на самом деле работает правильно:
#include<cstring>
char const* func(char const* a, char const* b)
{
return std::strcmp(a, b)<0 ? b : a;
}
#include<iostream>
int main()
{
const char* a = "First";
const char* b = "Second";
const char* c = "Third";
std::cout << func(func(a, b), c) << std::endl;
std::cin.ignore();
return 0;
}
, который возвращает «третий»
Проблема возникает при изменении func(func(a, b), c)
в main на func(a, b, c)
. Это потому, что вы комбинируете указатели со ссылками на указатели. Это возможно сделать, но не так, как вы.
Теперь, если вы вызываете func(a, b, c)
, все аргументы передаются второй функции по ссылке . Чтобы продемонстрировать, что это значит, рассмотрим следующий код:
#include<iostream>
int main()
{
const char* a = "First";
std::cout << "a: " << (void*)a << ", &a:" << &a << std::endl;
const char* b = "Second";
std::cout << "b: " << (void*)b << ", &b:" << &b << std::endl;
const char* c = "Third";
std::cout << "c: " << (void*)c << ", &c:" << &c << std::endl;
std::cin.ignore();
return 0;
}
Для меня это возвращает:
a: 00938B30, &a:00B9FEEC
b: 00938BE4, &b:00B9FEE0
c: 00938BF4, &c:00B9FED4
См? a
- это указатель, который содержит адрес, , но есть также адрес, который указывает на a
! . Они передаются, когда вы звоните по ссылке.
Однако внутри этой (второй func
) функции вы вызываете первую func
, которая копирует значения указателя, поскольку она не передает аргументы по ссылке. Эти локальные копии являются временными значениями, которые уничтожаются, когда функции выходят из области видимости. Проблема возникает, когда вторая (func
) функция пытается записать адрес этой локальной копии в значение, вызываемое по ссылке.
Хорошо, я не знаю, следите ли вы за мной здесь. Давайте продемонстрируем, что происходит в памяти на примере:
#include<cstring>
#include<iostream>
char const* func(char const* const a, char const* const b)
{
std::cout << "Func1:\n";
std::cout << "local: a: " << (void*)a << "<--copy, &a:" << &a << "<--*different from main!*\n";
std::cout << "local: b: " << (void*)b << "<--copy, &b:" << &b << "<--*different from main!*\n";
return std::strcmp(a, b)<0 ? b : a;
}
char const*& func(char const*& a, char const*& b, char const*& c)
{
std::cout << "Func2:\n";
std::cout << "ref: a: " << (void*)a << "<--original, &a:" << &a << "<--original\n";
std::cout << "ref: b: " << (void*)b << "<--original, &b:" << &b << "<--original\n";
std::cout << "ref: c: " << (void*)c << "<--original, &c:" << &c << "<--original\n";
char const* const out = func(func(a, b), c);
std::cout << "Func2:\n";
std::cout << "local: out: " << (void*)out << ", &out:" << &out << " (cannot return this local variable to a reference)\n";
return c; // just to fix it for now
}
int main()
{
std::cout << "Main:\n";
const char* a = "First";
std::cout << "a: " << (void*)a << ", &a:" << &a << "\n";
const char* b = "Second";
std::cout << "b: " << (void*)b << ", &b:" << &b << "\n";
const char* c = "Third";
std::cout << "c: " << (void*)c << ", &c:" << &c << "\n";
func(a, b, c);
std::cin.ignore();
return 0;
}
Для меня это возвращает:
Main:
a: 00F38D00, &a:005EF78C
b: 00F38C00, &b:005EF780
c: 00F38D08, &c:005EF774
Func2:
ref: a: 00F38D00<--original, &a:005EF78C<--original
ref: b: 00F38C00<--original, &b:005EF780<--original
ref: c: 00F38D08<--original, &c:005EF774<--original
Func1:
local: a: 00F38D00<--copy, &a:005EF5A4<--*different from main!*
local: b: 00F38C00<--copy, &b:005EF5A8<--*different from main!*
Func1:
local: a: 00F38C00<--copy, &a:005EF5A8<--*different from main!*
local: b: 00F38D08<--copy, &b:005EF5AC<--*different from main!*
Func2:
local: out: 00F38D08, &out:005EF680 (cannot return this local variable to a reference)
живое демо
Надеюсь, это достаточно ясно для вас