为什么C++在迭代容器时调用复制构造函数

Why does C++ invoke a copy constructor when iterating a container?

本文关键字:调用 复制 构造函数 C++ 迭代 为什么      更新时间:2023-10-16
void ParticleGeneratorController::generate() {
    for( unsigned i = 0; i < generators.size(); i++) {
        ParticleGenerator generator = *generators[i];
        generator.update();
    }
}

似乎调用复制构造函数或其他东西,但我没有定义一个。我只有一个显式的默认构造函数。

https://github.com/ChrisLundquist/Waveform/blob/master/src/models/particle_generator.h

鉴于我上面的代码,通过测试失败。 https://github.com/ChrisLundquist/Waveform/blob/master/spec/controllers/particle_generator_controller_spec.cpp#L21

当写为

void ParticleGeneratorController::generate() {
    for( unsigned i = 0; i < generators.size(); i++) {
        generators[i]->update();
    }
}

测试通过。

为什么在第一个实现中调用复制构造函数?编译器如何生成它?

此行会导致复制:

ParticleGenerator generator = *generators[i];

如果未显式指定复制构造函数(或赋值运算符(,编译器将自动生成一个。如果您希望阻止复制对象,则可以声明而不是定义复制构造函数和赋值运算符,如下所示private

ParticleGenerator
{
public:
private:
    ParticleGenerator(const ParticleGenerator&);
    ParticleGenerator& operator=(const ParticleGenerator&);
};

每次执行此操作时,您都会创建一个新ParticleGenerator

ParticleGenerator generator = *generators[i];

这是一个副本初始化,并且,鉴于您没有显式提供复制构造函数,则使用编译器合成的构造函数。

以下行执行复制:

ParticleGenerator generator = *generators[i];

如果未定义复制构造函数,编译器会自动为您执行此操作。为了禁用它,您可以将复制构造函数声明为私有而不实现它。通常这也应该使用复制赋值运算符来完成。

如果要避免在代码中创建副本,只需创建一个指针即可。写

ParticleGenerator * generator = generators[i];
generator->update();

而是进入您的循环。或

generators[i]->update();

如果你想真的短手。