问题描述
我需要实例化一个类SpriteWithTimer
,并且新对象将自己添加到向量vsprites
中。
#include <vector>
...
class SpriteWithTimer {
public:
SpriteWithTimer();
~SpriteWithTimer();
...
};
static std::vector<SpriteWithTimer> vsprites;
int main()
{
...
}
...
SpriteWithTimer::SpriteWithTimer(){
...
vsprites.push_back(this);
};
no matching function for call to ‘std::vector<SpriteWithTimer>::push_back(SpriteWithTimer*)’
no instance of overloaded function "std::vector<_Tp,_Alloc>::push_back [with _Tp=SpriteWithTimer,_Alloc=std::allocator<SpriteWithTimer>]" matches the argument list -- argument types are: (SpriteWithTimer *) -- object type is: std::vector<SpriteWithTimer,std::allocator<SpriteWithTimer>>
谢谢!
解决方法
存储在向量中的对象始终是全新的,单独构造的对象。因此,您不能将在其他位置创建的对象存储到矢量。您可以存储:
- 该对象的副本:
push_back(*this)
, - 具有内容已从该对象移出的对象:
push_back(std::move(*this))
, - 指向该对象的指针
push_back(this)
。
您需要选择适合您情况的内容。在第三种情况下,请注意悬空指针。基本上,您应该保证在使用这些指针之前,指向对象的生命周期不会结束。
, Foo
个对象的向量?
如果您想要一个Foo
对象的向量(而不是Foo
对象的 pointers ),则需要取消引用this
复制到传入的非const容器引用的成员函数中的> pointer 。例如:
#include <vector>
struct Foo {
int x{42};
void addMeToVector(std::vector<Foo>& v) & {
// _copies_ the `Foo` object in v
v.push_back(*this);
}
};
int main() {
std::vector<Foo> v;
Foo f1{};
f1.addMeToVector(v);
}
请注意,我们已将 ref-qualifier &
应用于addMeToVector
成员函数,以避免临时对象试图将自己添加到向量参数中:>
Foo{}.addMeToVector(v);
// error: 'this' argument to member function 'addMeToVector'
// is an rvalue,but function has non-const lvalue ref-qualifier
因为与直接将临时对象直接推回(或嵌入)到容器中相比,这可能是出乎意料的。
如果您实际上确实想通过成员函数明确允许移动说临时对象到容器中,并且由于某些原因不想直接使用向量中的push_back(T&&)
重载,您可以为&&
限定词添加一个重载:
struct Foo {
int x{42};
void addMeToVector(std::vector<Foo>& v) & {
// copies in (push_back(const T&) overload)
v.push_back(*this);
}
void addMeToVector(std::vector<Foo>& v) && {
// moves in (push_back(T&&) overload)
v.push_back(std::move(*this));
}
};
此重载方案将允许移入临时对象,将在其中复制左值。
您还可以移动非临时对象,但这可能会导致调用站点上的整个生命周期混乱,因为被调用对象(一个左值)将自己移入传递给它的参数中,并且在以后不应再使用成员函数调用,这将是一个很奇怪(且出乎意料)的语义。
指向Foo
对象的指针的向量?
[...]我需要一个指针向量,而不是对象本身。
如果您认为每个Foo
对象都是唯一的,并且它的所有权也应该是唯一的(例如,向其中添加Foo
对象时转移到向量) ,您可能需要重新考虑对象本身是否真的需要将其添加到容器中,并使用std::unique_pointer
:s容器而不是原始指针。由于原始指针本身不会保存任何有关所有权的信息,因此如果不谨慎处理,它们通常会带来生命周期问题。