【发布时间】:2013-09-03 06:29:30
【问题描述】:
一个模板类和一个普通类:
template <typename Type>
class Holder
{
public:
Holder(const Type& value) : held_(value)
{
cout << "Holder(const Type& value)" << endl;
}
Type& Ref() { return held_; }
private:
Type held_;
};
class Animal
{
public:
Animal(const Animal& rhs) { cout << "Animal(const Animal& rhs)" << endl; }
Animal() { cout << "Animal()" << endl; }
~Animal() { cout << "~Animal" << endl; }
void Print() const { cout << "Animal::Print()" << endl; }
};
然后我想用这个语句Holder<Animal> a(Animal()); 实例化一个Holder<Animal>,但是它失败了。我的意思是 Animal() 不被视为临时对象。而且这个语句没有调用Holder的构造函数。
如果有人可以解释?我不清楚。我猜a 在这里变成了一种类型。然后,我使用Holder<Animal> a = Holder<Animal>(Animal());,效果很好。所以,这里有一些情况:
Holder<Animal> a(Animal()); a.Ref().Print(); // errorHolder<Animal> a = Holder<Animal>(Animal()); a.Ref().Print(); // okHolder<int> b(4); b.Ref() = 10; cout << b.Ref() << endl; //ok
能解释一下吗?我只是对第一个陈述有点困惑。以及该语句导致的错误信息:
GCC4.7.2:error: request for member 'Ref' in 'a', which is of non-class type 'Holder<Animal>(Animal (*)())'
VS10:error C2228: left of '.Ref' must have class/struct/union,error C2228: left of '.Print' must have class/struct/union
【问题讨论】:
-
一个好问题...我真的不知道答案。但是
Animal()不会被当作临时对象吗?它不会立即超出范围吗? -
@Dariusz 不,它会持续到达到
;,即直到a的构造函数完成。 -
@ArneMertz 好的,“立即”是指在该行执行完成之后,即在构造函数之后。那么既然我们引用了那个对象,那么这个引用会变得无效吗? ...啊,不会的,持有人成员
held_不是参考,没关系。 -
@Dariusz 这是 C++03 的方法——临时文件被复制,副本仍然存在。在 C++11 中,构造函数将按值获取参数并从中移动构造成员变量。这样临时的
Animal会被移动两次并最终在held_成员变量中。
标签: c++ templates most-vexing-parse