неверная инициализация неконстантной ссылки типа char char * & из временного типа const char * - PullRequest
0 голосов
/ 30 июня 2018

После компиляции следующей программы я получаю эту ошибку:

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

char const*& func(char const*& a, char const*& b,char const*& c)
{
        return func(func(a,b),c);
}
int main()
{
    const char* a="First";
    const char* b="Second";
    const char* c="Third";

    func(func(a,b),c); //ERROR
    return 0;
}

Вопросы:

1. Ошибка выдается из-за возвращаемого значения func (a, b), но я не знаю причину этого.

2. Почему временный объект создается при возврате из функции (char const *, char const *)? Это создано, потому что сторона вызывающего абонента не имеет переменной для сбора возвращаемого значения?

РЕДАКТИРОВАТЬ: Эта ошибка обсуждалась в других темах, но сценарий другой (хотя, мы надеемся, причина должна быть та же) в этом случае, поэтому я задал этот вопрос, потому что объяснение не очевидно в этом сценарии , Пожалуйста, не отмечайте его как дубликат.

1 Ответ

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

Сначала я неправильно оценил ваш вопрос, потому что неправильно прочитал ваш код. Собственно, в вашем коде 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)

живое демо

Надеюсь, это достаточно ясно для вас

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