当您考虑编译器将为您生成一个默认构造函数、一个默认复制构造函数和一个默认复制赋值运算符时,这一点变得很明显,以防您的结构/类不包含引用成员。然后,想想标准允许你在临时对象上调用成员方法,也就是说,你可以在非常量临时对象上调用非常量成员。
看这个例子:
struct Foo {};
Foo foo () {
return Foo();
}
struct Bar {
private:
Bar& operator = (Bar const &); // forbid
};
Bar bar () {
return Bar();
}
int main () {
foo() = Foo(); // okay, called operator=() on non-const temporarie
bar() = Bar(); // error, Bar::operator= is private
}
如果你写
struct Foo {};
const Foo foo () { // return a const value
return Foo();
}
int main () {
foo() = Foo(); // error
}
即,如果您让函数 foo() 返回一个const临时变量,则会发生编译错误。
为了使示例完整,以下是如何调用 const temporarie 的成员:
struct Foo {
int bar () const { return 0xFEED; }
int frob () { return 0xFEED; }
};
const Foo foo () {
return Foo();
}
int main () {
foo().bar(); // okay, called const member method
foo().frob(); // error, called non-const member of const temporary
}
您可以将临时的生命周期定义为在当前表达式内。这就是为什么您还可以修改成员变量的原因;如果你不能,那么调用非 const 成员方法的可能性将是荒谬的。
编辑:这是所需的引文:
12.2 临时对象:
- 3) [...] 临时对象作为评估完整表达式 (1.9) 的最后一步被销毁,该完整表达式 (从词法上) 包含它们被创建的点。[...]
然后(或更好,之前)
3.10 左值和右值:
- 10) 对象的左值是修改对象所必需的,但在某些情况下也可以使用类类型的右值来修改其所指对象。[示例:为对象(9.3)调用的成员函数可以修改该对象。]
还有一个使用示例:http ://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Named_Parameter