C++ 当隐式转换发生时,对象是否会失去常量?
我做了一个小实验,但我不明白结果C++ 当隐式转换发生时,对象是否会失去常量?,c++,object,constants,implicit-conversion,C++,Object,Constants,Implicit Conversion,我做了一个小实验,但我不明白结果 class C { public: operator int() const { std::cout << "I'm const" << std::endl;} operator int(){ std::cout << "I'm not const" << std::endl;} }; void f(int){}; int main() { f(C()); } g(C())输出“I取常数” 一个临
class C {
public:
operator int() const { std::cout << "I'm const" << std::endl;}
operator int(){ std::cout << "I'm not const" << std::endl;}
};
void f(int){};
int main()
{
f(C());
}
g(C())输出“I取常数”
一个临时变量不是常数:
C(); // not const
如果您想经常引用它,请将其转换为:
f(static_cast<const C&>(C()));
f(static_cast(C());
关键是,其成员函数(此处为转换运算符)被调用的对象不是常量。这与转换的结果无关
结果实际上也不需要是常数。假设我们添加另一个类:
class D { };
class C {
// ...
operator D() { return D(); }
};
int main()
{
D d;
static_cast<D>(C()) = d; // OK: assign d to the result of the conversion
// static_cast<int>(C()) = 6; // Error: left-hand side is not an lvalue
}
D类{};
C类{
// ...
运算符D(){return D();}
};
int main()
{
D;
static_cast(C())=d;//确定:将d分配给转换结果
//static_cast(C())=6;//错误:左侧不是左值
}
这可能会让你大吃一惊,但这是完全合法的C++:
class C { } ;
int main()
{
C d ;
C() = d ;
}
看看证据。所以
C()
是左值。你为什么说“输”?你为什么一开始就希望有人成为警察?好吧。所以没有任何东西默认为const,但是为什么g的行为与C::operator int()不同呢?不,与constness无关,只与左值/右值有关。您不能分配给右值,右值是转换为int的结果。我正在编辑以添加此示例。好的。但是为什么在调用g(C())时使用g(C const&)而在调用int(C())时使用int(C&)呢?@Ragnar:这是一个关于右值的大谜团。我不知道为什么,但您可以对右值调用任何您喜欢的非常量方法,但它不能作为非常量引用传递到用户定义的函数中。我自己也觉得这个问题非常复杂和奇怪,我从来没有看到过令人满意的解释。@Ragnar:temporary只绑定到C const&
,但它本身并不是常数。这仅仅是一个语言设计决策(这是非常聪明的),但是如果必须的话,您可以自由地抛弃常量并修改对象,因为临时对象本身并不是不变的。还请注意,临时值将很高兴地绑定到可变的C&
“是左值”错误。这是一个右值。也许你相信左值的意思是“可以在左边”?事实并非如此。左值就是左值。它“毫无意义”。这是一组(大部分是任意的)规则。C()
是一种“显式类型转换(函数表示法)”[expr.type.conv](它不将任何内容转换为某些内容)。“表达式T()
(…)创建指定类型的prvalue”“创建类类型的临时值(…)创建prvalue的转换”[class.temporary]在历史分类中,它只是一个右值。无论如何,表达式引用了一个类对象,它有一个地址,可以有一个名为…“Lvalue意味着Lvalue”的成员函数。这意味着对于Lvalue,rvalue没有一个可爱的定义。。。确切的定义涉及一长串案例,描述中有一长串特定属性。如果你想对左值做一个简短的定义:“你可以把操作符的地址应用到它上面”,它很短,很可爱,对于原语类型和用户定义的类型都是错误的。“我不认为C()符合简单类型说明符typename说明符中的任何一个”真的???你认为[expr.type.conv]适用于什么?
class C { } ;
int main()
{
C d ;
C() = d ;
}