在C ++中为对象赋值

时间:2014-09-21 21:55:29

标签: c++

我可以被认为是编程的初学者。我正在尝试用C ++编写一个可以保存多维数据的类(例如MxN矩阵)。我不想通过矢量矢量的方式来做。我写了下面这段代码,但是当我用g ++编译它时,我得到了分段错误:11错误。另一方面,当我尝试使用Xcode编译它时,它在行

给出“线程1:EXC_BAD_ACCESS(代码= 1,地址= 0x0)”
particles[i].x = x0 + R*cos(theta*i);

所以,我想我得到了一种与为对象分配值相关的内存错误。

在C ++中是否允许使用这种语法:

particles_old[i].x = particles[i].x;

或者我可以这样:

// say A is a class with x a vector this time, instead of a double data. 
// in nested for loops
vector<A> B;
B[i].x[j] = some value;

我知道它有点模糊,但从语法的角度来看它至少是正确的吗?

#include <iostream>
#include <cmath>
#include <fstream>
#include <string>
#include <vector>
#include <random>
using namespace std;

class Particle{
public:
    double x; // x position
    double y; // y position
    double vx; // velocity in the x direction
    double vy; // velocity in the y direction
    double Fx; // force in the x direction
    double Fy; // force in the y direction

    // Default constructor
    Particle()
    : x(0.0),y(0.0),vx(0.0),vy(0.0),Fx(0.0),Fy(0.0){
    }
};

int main() {

    const float pi = 3.14;
    int N = 30; // Number of 'particles' that make up the cell
    float theta = 2*pi/N; // Angle between two particles in radians
    float x0 = 0; // Center of the cell [x]
    float y0 = 0; // Center of the cell [y]
    float R = 5e-6; // Radius of the cell
    vector<Particle> particles; // particles

    // Assigning the initial points onto the circle
    for(int i = 0; i < N; i++) {
        particles[i].x = x0 + R*cos(theta*i);
        particles[i].y = y0 + R*sin(theta*i);
    }

    float k = 4.3e-7; // Spring constant connecting the particles
    float m = 2e-8; // Mass of the particles

    // Calculating the initial spring force between the particles on the cell
    particles[0].Fx = -k*(particles[1].x - particles[N].x);
    particles[0].Fy = -k*(particles[1].y - particles[N].y);
    for(int i = 1; i < N-1; i++) {
        particles[i].Fx = -k*(particles[i+1].x - particles[i-1].x);
        particles[i].Fy = -k*(particles[i+1].y - particles[i-1].y);
    }
    particles[N].Fx = -k*(particles[0].x - particles[N-1].x);
    particles[N].Fy = -k*(particles[0].y - particles[N-1].y);

    // Initial velocities are given to each particle randomly from a Gaussian distribution
    random_device rdx; // Seed
    default_random_engine generatorx(rdx()); // Default random number generator
    random_device rdy; // Seed
    default_random_engine generatory(rdy()); // Default random number generator
    normal_distribution<float> distributionx(0,1); // Gaussian distribution with 0 mean and 1 variance
    normal_distribution<float> distributiony(0,1); // Gaussian distribution with 0 mean and 1 variance
    for(int i = 0; i < N; i++) {
        float xnumber = distributionx(generatorx);
        float ynumber = distributiony(generatory);
        particles[i].vx = xnumber;
        particles[i].vy = ynumber;
    }


    // Molecular dynamics simulation with velocity Verlet algorithm

    // 'Old' variables
    vector<Particle> particles_old;

    for(int i = 0; i < N; i++) {
        particles_old[i].x = particles[i].x;
        particles_old[i].y = particles[i].y;
        particles_old[i].vx = particles[i].vx;
        particles_old[i].vy = particles[i].vy;
        particles_old[i].Fx = particles[i].Fx;
        particles_old[i].Fy = particles[i].Fy;
    }

    // Sampling variables
    int sampleFreq = 2;
    int sampleCounter = 0;

    // MD variables
    float dt = 1e-7;
    float dt2 = dt*dt;
    float m2 = 2*m;
    int MdS = 1e+4; // Molecular dynamics step number

    // MD
    for(int j = 0; j < MdS; j++) {

        // Update x
        for(int i = 0; i < N; i++) {
            particles[i].x = particles_old[i].x + dt*particles_old[i].vx + dt2*particles_old[i].Fx/m2;
            particles[i].y = particles_old[i].y + dt*particles_old[i].vy + dt2*particles_old[i].Fy/m2;
        }

        // Update F
        particles[0].Fx = -k*(particles[1].x - particles[N].x);
        particles[0].Fy = -k*(particles[1].y - particles[N].y);
        for(int i = 1; i < N-1; i++) {
            particles[i].Fx = -k*(particles[i+1].x - particles[i-1].x);
            particles[i].Fy = -k*(particles[i+1].y - particles[i-1].y);
        }
        particles[N].Fx = -k*(particles[0].x - particles[N-1].x);
        particles[N].Fy = -k*(particles[0].y - particles[N-1].y);

        // Update v
        for(int i = 0; i < N; i++) {
            particles[i].vx = particles_old[i].vx + dt*(particles_old[i].Fx + particles[i].Fx)/m2;
            particles[i].vy = particles_old[i].vy + dt*(particles_old[i].Fy + particles[i].Fy)/m2;
        }

        // Copy new variables to old variables
        for(int i = 0; i < N; i++) {
            particles_old[i].x = particles[i].x;
            particles_old[i].y = particles[i].y;
            particles_old[i].vx = particles[i].vx;
            particles_old[i].vy = particles[i].vy;
            particles_old[i].Fx = particles[i].Fx;
            particles_old[i].Fy = particles[i].Fy;
        }

    }

}

提前致谢。

4 个答案:

答案 0 :(得分:2)

// Assigning the initial points onto the circle
for(int i = 0; i < N; i++) {
    particles[i].x = x0 + R*cos(theta*i);
    particles[i].y = y0 + R*sin(theta*i);
}

在您输入该循环时,您的矢量为空。然后,您尝试使用operator[]访问其中的元素。如果您查看有关std::vector operator[]的信息,请说明以下内容:

&#34;便携式程序永远不应该使用超出范围的参数n来调用此函数,因为这会导致未定义的行为。&#34;

你正是这样做的,访问一个超出范围的元素,在这种情况下,未定义的行为是崩溃。

将该循环更改为:

// Assigning the initial points onto the circle
for(int i = 0; i < N; i++) {
    // Create and initialize a new particle
    Particle newParticle;
    newParticle.x = x0 + R*cos(theta*i);
    newParticle.y = y0 + R*sin(theta*i);
    // add it to the vector
    particles.push_back(newParticle);
}

为您明确创建新的Particle,然后使用std::vector方法将其添加到.push_back()

注意这两行:

particles[N].Fx = -k*(particles[0].x - particles[N-1].x);
particles[N].Fy = -k*(particles[0].y - particles[N-1].y);

可能会因为完全相同的原因而崩溃,因为在那时你已经完全填充了[0 .. N-1],你还没有在插槽N中放置一个元素。我会留给你解决这个问题,因为解决方案与for循环完全相同。

答案 1 :(得分:2)

嘿,您需要在将粒子添加到列表中时初始化粒子,例如

for (int i = 0; i < N+1; i++) { // You are accessing [N] directly in your code..
    Particle p;
    p.x = x0 + R*cos(theta*i);
    p.y = y0 + R*sin(theta*i);
    particles.push_back(p);
}

我将代码简化了一下,因为你直接使用[N] +1就在那里,你应该在代码中改为[N-1],否则你将超出你的向量。

你将粒子推向矢量,在矢量的末尾,记住你的矢量是空的!我相信这可以做得更好,说实话我在这里有点生疏我的自我:)拿起我的“婴儿语言”和那里已经实现的所有很酷的功能。

我不确定我是否按照你的问题,但如果你想看看简单的2维数组there is a rather usefull post here at SO

无论如何,我希望它可以帮助你。

答案 2 :(得分:2)

你已经有两个很好的答案了。这是另一种变体:

如果您事先知道矢量的大小,您可以按如下方式定义:

vector<Particle> particles(N);  // create a vector with N particles default initialized. 

其余的代码应该可以工作,因为粒子[i]将引用已经存在的粒子。

是的,old_particles = particles;将复制整个矢量。无需循环中的元素copyelement。

答案 3 :(得分:1)

除了其他答案,我也会这样做

在创建粒子之前

particles.reserve(N);(或N+1),因此向量不必在循环期间重新分配内存

或甚至将particles声明为vector<Particle> particles(N);(或再次N+1),因此向量已经填充了默认初始化粒子,您只需像以前一样分配它们的值。 / p>

选择NN+1取决于行

particles[0].Fx = -k*(particles[1].x - particles[N].x);

您似乎在这里访问N元素,如果它不是拼写错误,则矢量大小应为N + 1