为什么类中的静态数据成员在发送到函数时更新不正确
Why Static data member in class updates not correctly when sending it to a function?
执行后,Goomba::liveGoombas
等于某个负值。我对它进行了调试,但不明白为什么它会比构造函数多次启动析构函数。为什么它在这里工作不正确?
// Here is a simple Goomba class. It just keeps track of how many Goombas are alive.
class Goomba
{
public:
static int liveGoombas;
Goomba() { liveGoombas++; }
~Goomba() { liveGoombas--; }
};
int Goomba::liveGoombas = 0;
// And a Goomba legion class. Please don't change this class.
class GoombaLegion
{
public:
void add(Goomba goomba)
{
goombas.push_back(goomba); //it seems that something wrong in this function
}
private:
std::vector<Goomba> goombas;
};
void goombas()
{
{
GoombaLegion legion;
}
// The legion went out of scope and was destroyed. But how many Goombas are alive?
std::cout << "There are " << Goomba::liveGoombas << " live goombas" << std::endl;
}
int main()
{
goombas();
}
如果不指定自己的实现,编译器将创建其他构造函数。这些是复制构造函数,在C++11及更新版本的情况下,还有移动构造函数。
当您看到负计数时,可以通过使用编译器生成的构造函数之一来解释。因此,实例数量增加,但liveGoombas
没有。
为了获得准确的计数,你应该将Goomba更改为如下所示。
如果您正在使用启用了移动语义的编译器(C++0x/C++11及更新版本):
class Goomba
{
public:
static int liveGoombas;
Goomba() { liveGoombas++; }
Goomba(const Goomba&) { liveGoombas++; }
Goomba(Goomba&&) { liveGoombas++; }
// Need to explicitly state we want default or it will be deleted
// due to the above move constructor having been defined.
Goomba & operator = (const Goomba&) = default;
// Not really essential but including for completeness
Goomba & operator = (const Goomba&&) = default;
~Goomba() { liveGoombas--; }
};
否则:
class Goomba
{
public:
static int liveGoombas;
Goomba() { liveGoombas++; }
Goomba(const Goomba&) { liveGoombas++; }
~Goomba() { liveGoombas--; }
};
默认的赋值操作符很好,因为它们不创建新实例,只修改现有实例。因此,他们不应该更改实例计数。
当将值Goomba传递给正在静默复制的函数时,此外,您需要使用pushback操作和向量偶尔进行的可能的重新定位来复制goombas。
为了查看(在代码中)您隐式使用这些函数的位置(默认构造的复制和赋值运算符),将它们定义为私有的且没有实现,编译器将在引用需要这些运算符的行时出错。
您可能想要沿着构造函数的行给出复制构造函数和赋值的实现。
C++11
如果定义移动构造函数:
Goomba(const Goomba&&) { liveGoombas++; }
你最好让编译器为你生成这两个:
Goomba& operator=(const Goomba&&) = default;
Goomba& operator=(const Goomba&) = default;
否则它们将被自动删除。
如果你没有定义移动构造函数,赋值不会被删除,但明确声明默认赋值对你来说仍然是个好主意:
Goomba& operator=(const Goomba&) = default;
其他答案都不完全准确。
首先,不要将move构造函数声明为接受const
参数,这是毫无意义的,也不是惯用的,因为您最多可以具有与副本相同的性能;此外,移动意味着对"移动自"对象的修改。
其次,如果您执行以下操作,则Goomba(Goomba&&) { liveGoombas++; }
会中断:
Goomba g;
Goomba b(std::move(g));
std::cout << Goomba::liveGoombas << std::endl; // prints 2, is that really correct?
这应该可以为单线程程序(此处为实时版本)提供技巧:
class Goomba
{
bool alive;
public:
static int liveGoombas;
Goomba()
: alive(true)
{ liveGoombas++; }
Goomba(const Goomba& rhs)
: alive(rhs.alive)
{
if (alive)
liveGoombas++;
}
// Move constructor
Goomba(Goomba&& rhs)
: alive(std::move(rhs.alive))
{
if (alive)
liveGoombas++;
rhs.kill(); // modifies moved from object!
}
Goomba& operator =(const Goomba& rhs)
{
kill();
alive = rhs.alive;
if (alive)
liveGoombas++;
return *this;
}
// Move assignment
Goomba& operator =(Goomba&& rhs)
{
kill();
alive = std::move(rhs.alive);
if (alive)
liveGoombas++;
rhs.kill(); // modifies moved from object!
return *this;
}
~Goomba() {
kill();
}
private:
void kill() {
if (alive) {
liveGoombas--;
alive = false;
// insert other death/dying code here
}
}
};
注意:通常会将移出的对象视为"已销毁",尽管事实并非如此。
- g++ 说函数不存在,即使包含正确的标头
- 将参数传递给泛型 lambda 时复制构造函数不正确
- 非静态成员函数的 decltype 格式不正确吗?
- 数组为此合并排序函数提供了正确的输出,但向量给出了不正确的输出.出了什么问题?
- 我的动态链接队列在同一输出流中调用时不正确地输出三个返回函数
- 编译器在构造函数中计算的成员偏移量不正确
- 为什么在template函数广播中把两个extensor表达式加在一起不正确
- 从模板化类虚拟函数中调用的模板函数不正确
- 为什么不调用预期的函数?我是否对类型特征的理解不正确?
- 将函数的地址转换为UINTPTR_T给我不正确的结果
- 模板实例化失败:编译器选择不正确的重载函数
- 为什么构造函数C++接受不正确的类型作为参数?
- 不正确的输出和变量未用Eclipse CDT初始化构造函数
- 不正确的成员构造函数定义
- 调用求和或获取乘积的函数不正确
- 当const在另一行处的const时,doxygen parse const成员函数不正确
- 模板中调用的虚拟函数不正确
- C++将数组传递给函数不正确
- 构造函数不正确和隐式删除
- c++ If, else If不读else If.或发现函数不正确