2010-10-09 2 views
11

После обширного чтения ISO/IEC 14882, Programming language – C++ я все еще не уверены, почему const необходим для неявного преобразования в определяемого пользователем типа с помощью одного аргумента конструктора, как следующийПочему const для неявного преобразования?

#include <iostream> 

class X { 
public: 
    X(int value) { 
     printf("constructor initialized with %i",value); 
    } 
} 

void implicit_conversion_func(const X& value) { 
    //produces "constructor initialized with 99" 
} 

int main (int argc, char * const argv[]) { 
    implicit_conversion_func(99); 
} 



Начиная с раздела 4 линии 3

Выражение e может быть неявно преобразовано в тип T тогда и только тогда, когда объявление T t = e; хорошо сформирована, для некоторой изобретенной временной переменной t (8.5). Для некоторых языковых конструкций требуется, чтобы выражение было преобразовано в логическое значение. Выражение e, отображаемое в таком контексте, называется контекстно преобразованным в bool и хорошо сформировано тогда и только тогда, когда декларация bool t (e); хорошо сформирована, для некоторой изобретенной временной переменной t (8.5). Эффект либо неявного преобразования является таким же, как выполнение объявления и инициализации, а затем использование временной переменной в результате преобразования. Результатом является lvalue, если T - ссылочный тип lvalue (8.3.2) и rvalue в противном случае. Выражение e используется как lvalue тогда и только тогда, когда инициализация использует его как lvalue.

После этого я нашел раздел инициализаторов, связанные с определенным пользователем типов в 8,5 линии 6

Если программа вызывает для инициализации по умолчанию объекта константного-квалифицирован типа Т, Т должен быть типом класса с предоставленным пользователем конструктором по умолчанию.

Наконец я закончил в строке 2 12,3 об определенных пользователем преобразований в котором говорится

преобразования, определенные пользователем, применяются только там, где они являются однозначными (10.2, 12.3.2).

Излишне говорить, что 10.2 и 12.3.2 не отвечали на мой вопрос.

  1. Может кто-нибудь пролить некоторый свет на то, что эффект const имеет на неявные преобразования?
  2. Использует ли const преобразование «однозначно» по 12,3 строки 2?
  3. const как-то влияет на значение lvalue vs. rvalue в разделе 4?
+1

Не любите ли вы C++? – 2010-10-09 04:02:15

ответ

13

Это не имеет особого отношения к преобразованию неявное. Более того, это не имеет особого отношения к конверсии. Это действительно о rvalues ​​ vs. lvalues ​​.

Когда вы конвертируете 99 в тип X, результатом является rvalue. В C++ результаты преобразований всегда rvalues ​​(если вы не конвертируете в ссылочный тип). В C++ запрещено использовать не-const ссылки на rvalues.

Например, этот код не компилируется

X& r = X(99); // ERROR 

, потому что он пытается прикрепить неконстантную ссылку на RValue. С другой стороны, этот код является штрафным

const X& cr = X(99); // OK 

, потому что вполне нормально прикладывать ссылку на константу r.

То же самое происходит и в вашем коде. Тот факт, что он подразумевает неявное преобразование, не имеет отношения к делу. Вы можете заменить неявное преобразование с явным один

implicit_conversion_func(X(99)); 

и в конечном итоге с той же ситуацией: с const компилирует, без const это не делает.

Опять же, единственная роль, которую играет здесь конверсия (явная или неявная), заключается в том, что она помогает нам генерировать значение rvalue. В общем, вы можете произвести RValue каким-либо другим способом и запустить в тот же вопрос

int &ir = 3 + 2; // ERROR 
const int &cir = 3 + 2; // OK 
+0

"_ Когда вы конвертируете 99 в тип X, результатом будет rvalue._" № **. Rvalue - это выражение. ** Преобразование '99' в' X' приводит к временному объекту. – curiousguy

+0

@curiousguy: Хотя понятие «rvalue» твердо привязано к выражению, термин «rvalue» может использоваться для обозначения самого выражения, а также для результата, который он дает. Стандарт языка фактически использует понятие «rvalue result» намного чаще, чем «выражение rvalue». (Очевидно, оба на самом деле предназначены для обозначения одного и того же). Более того, спецификация языка четко и явно заявляет в 5.2.3, что результатом функционального стиля является rvalue. Период. Тот факт, что он также оказывается «временным объектом», вряд ли имеет значение здесь. – AnT

+0

Не могли бы вы объяснить, что означает «rvalue»? – curiousguy

0

Per раздел 5.2.2 пункта 5, когда аргумент функции имеет const ссылочного типа, временная переменная автоматически если необходимо. В вашем примере результат rvalue от X(99) должен быть помещен во временную переменную, чтобы эту переменную можно было передать const ссылкой на implicit_conversion_func.

+0

«_ значение rvalue 99 должно быть помещено во временную переменную, чтобы эта переменная могла быть передана ссылкой (const) на конструктор X_» №. Параметр конструктора передается по значению; нет постоянной ссылки на 'int' и нет временных значений со значением 99.« Семантика создания неконстантного временного там в любом случае была бы довольно запутанной ».« Что насчет 'std :: string() =« Hello, мир "'? – curiousguy

+0

@curiousguy Хорошая точка - я думаю, что неправильно читаю OP. Временной является 'const X', инициализированным конструкцией с' 99' в качестве аргумента, а не 'const int'. Суть его остается, хотя: временный 'const' создается для удовлетворения аргумента' const & '. –

Смежные вопросы