Времена не ведут себя как постоянные
Мне неясно, принимает ли временный тип const или нет, в выражении, как показано ниже.
#include <iostream>
class X {
public:
X(int a) { i = a; cout << "X(int) [" << (int)this << "]" << endl; }
X& operator+(const X& x)
{
i += x.i;
cout << "X operator+(const X&) [" << (int)this << "]" << endl;
return *this;
}
~X() { cout << "~X [" << (int)this << "]" << endl; }
private:
int i;
};
int main()
{
X x = X(3) + X(4);
cout << "done" << endl;
return 0;
}
X(3)
ведет себя как неконстантный (потому что я могу позвонить operator+
, в то время как X(4)
ведет себя как const (потому что он нуждается в аргументе const в operator+
).
Может кто-то уточнить, что такое правильное понимание?
4 ответа
Когда речь идет о типах классов, при создании временного типа const этот временный будет const. И когда вы создаете временный неконстантный тип, он будет неконстантным. Вот и все. То есть, что касается точного типа, то здесь нет никакой связи между const и временными. Временный тип класса никогда не принимает const сам по себе. Это вы можете явно навязать const.
В вашем примере пустота X(3)
ни X(4)
является постоянным поскольку X(3)
не является const, вы можете вызвать неконстантный метод для него.
Неправильно говорить, что ваш X(4)
"ведет себя как const". Нет никаких признаков того, что он "ведет себя как постоянный" в вашем примере. То, что вы смогли инициализировать константную ссылку чем-то, не означает, что это константа.
В своем вопросе вы утверждаете, что вам "нужен постоянный аргумент в operator+
". Это неправильно. Вам не нужен константный аргумент в вашем operator+
, Ваш параметр x
объявляется как постоянная ссылка. Ссылка на const может быть легко связана с аргументами const, а также с неконстантными аргументами. В вашем случае константный ссылочный параметр x
связан с неконстантным временным аргументом X(4)
,
Исторически временные значения являются r-значениями, а r-значения не являются (и не могут быть) cv-квалифицированными. Это правило хорошо работает для типов, не относящихся к классам, или для типов классов без функций-членов; Так как постоянство вмешивается в разрешение перегрузки функций, необходимо сохранить квалификацию cv для временного объекта. Если функция возвращает просто X
, тогда временноене является const, и вы можете вызывать неконстантные функции на нем; если функции возвращаются X const
, тогда временным является const, и вы не можете вызывать неконстантные функции для него. Как правило, предпочтительнее возвращать типы классов как const
; т.е. X const f()
, скорее, чем X f()
, Но есть определенные исключения, и никто не делает этого, даже в тех случаях, когда это было бы более уместно. И, наконец, есть контексты, в которых вы не можете указать константность - например, преобразования типов стилей функций - где синтаксис не предоставляет средства для определения cv-квалификаторов (кроме как с помощью typedef).
Возможно, вы захотите взглянуть на вывод следующего кода:
class C
{
std::string myComment;
public:
C( std::string const& comment ) : myComment( comment ) {}
void f()
{
std::cout << "Non const " << myComment << std::endl;
}
void f() const
{
std::cout << "Const " << myComment << std::endl;
}
};
typedef C const CC;
C
c()
{
return C("function return value");
}
C const
cc()
{
return C("function return value");
}
int
main()
{
C("function style conversion").f();
CC("function style conversion").f();
c().f();
cc().f();
}
Вы можете позвонить неconst
члены временных Но вы не можете связать неconst
ссылка на временную.
В следующем коде:
X x = X(3) + X(4);
X(3)
создает временный неконстантный объект, который вызывает operator+
, проходя X(4)
который является другим временным неконстантным объектом в качестве аргумента константной ссылки на функцию.
Неконстантный объект может быть передан функции как константный объект (передача по ссылке), но константный объект не может быть передан неконстантной ссылкой на функцию. В этом разница.