Сомнение в вопросе об интервью C ++ - PullRequest
4 голосов
/ 04 октября 2010

Я прочитал Ответы на вопросы интервью C ++ , среди которых есть один, который озадачивает меня:

В: Когда временные переменные создаются компилятором C ++?

A: При условии, что параметр функции является «константной ссылкой», компилятор генерирует временную переменную следующими двумя способами.

a) Фактический аргумент - правильный тип, но это не Lvalue

double Cube(const double & num)
{
  num = num * num * num;
  return num;
}

double temp = 2.0;
double value = cube(3.0 + temp); // argument is a expression and not a Lvalue

b) Фактический аргумент имеет неправильный тип, но типа, который можно преобразовать в правильный тип

 long temp = 3L;
 double value = cuberoot(temp); // long to double conversion

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

Ответы [ 7 ]

7 голосов
/ 04 октября 2010

Я не вижу здесь ничего противоречивого. Если аргумент не является lvalue или имеет неправильный тип, ссылка не может быть прикреплена непосредственно к аргументу по очевидным причинам; отсюда необходимость промежуточного временного типа правильного типа. Ссылка прилагается к этому временному.

Функция Cube действительно повреждена (неправильно сформирована), поскольку пытается изменить значение const.

3 голосов
/ 04 октября 2010

Мне кажется неправильным - и gcc выдает ошибку:

const_ref.cpp: In function ‘double cube(const double&)’:
const_ref.cpp:3: error: assignment of read-only reference ‘num’
2 голосов
/ 04 октября 2010

Компилятор может создать временную переменную. Это не обязательно.

И да, Cube на самом деле не должен компилироваться.

1 голос
/ 04 октября 2010

Вам разрешается передавать результаты выражения (включая результаты неявного приведения) в ссылку на const. Обоснование состоит в том, что, хотя (const X & value) может быть дешевле в использовании, в зависимости от стоимости копирования типа X, чем (X value), эффект почти такой же; value привыкает, но не изменяется (за исключением некоторого рискованного чтения констант). Следовательно, безопасно создавать временный объект и передавать его функции.

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

Вы правы в том, что num = num * num * num; неверен. Это ошибка в тексте, но приводимый им аргумент верен.

0 голосов
/ 04 октября 2010

Да. Cube (), как вы показали здесь, не должен компилироваться.

0 голосов
/ 04 октября 2010

Я полагаю, что вы правы в том, что куб функции не скомпилирован. Во всяком случае, это должно произойти сбой, и это происходит на моем компиляторе (VC ++ 2008).

Что касается создания временного:

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

i) неверного типа для ссылки, и, II) может быть неявно преобразован в правильный тип.

В примере а) из вашего вопроса создается временный double для хранения значения 3.0 + temp. Затем вызывается Cube() со ссылкой const на временное. Это потому, что вы не можете иметь ссылку на 3.0 + temp, потому что это не переменная (это rvalue - результат выражения), и поэтому у нее нет адреса памяти, и вы не можете вернуть ссылку. Неявно, компилятор создаст временный double и затем присвоит ему значение 3.0 + temp.

В вашем примере б) у вас есть long, но для вашей функции требуется double. Компилятор неявно преобразует long в double. Это делается путем создания временного double, присвоения ему преобразованного значения temp, а затем создания ссылки const для временного объекта и передачи этой ссылки в cuberoot

0 голосов
/ 04 октября 2010

Поскольку в обоих примерах нет временного объекта правильного типа.

...