2017-03-05 1 views
-1

위로 돌아 가기 '98 내 이전 NeXT를 교체 한 후 objective-c에서 C++로 화학 모델을 변환했지만 실제로는 을 배울 수있는 기회를 얻지 못했습니다. C++. 지금은 컨테이너를 사용하는 방법을 배우는 것을 의미하는 현대적인 C++로 코드를 다시 작성합니다. 스마트 포인터 및 템플릿.참조로 반환 된 참조로 반환 된 C++ 벡터에 대한 참조를 저장하려고 시도했습니다.

출력 변수를 각 시간 단계가 아니라 앞면에서 한 번만 구문 분석해야하므로 원래 출력 변수 포인터 (float ***outVars)의 포인터 배열을 생성했습니다. 각 시간 간격 후에 포인터 목록을 실행할 수 있으며 outVars이 원래 데이터를 가리키고 있기 때문에 항상 모델의 현재 상태를 제공합니다.

코드를 행렬의 행렬에서 벡터 행렬로 변경하고 있습니다. 원래 벡터에 대한 참조가 아닌 벡터 사본 만 반환 할 수있었습니다. 벡터를 수정하고 싶지는 않습니다. 직접 읽기 액세스 만하면됩니다.

아직 온라인 답변을 찾지 못했다고 생각합니다. 내가 온라인으로 찾은 대부분은 단지 참조 용으로 돌아 가기 위해 std::vector<float> &을 사용한다고 말했지만 분명히 작동하지 않는다.

참조가 아닌 값 (변수라고 가정)을 복사 할 것이므로 하나의 메모를 보았 기 때문에 fvec2D &outVar2D; (아래 헤더 파일 참조)을 시도했습니다.

저는 const를 사용하거나 사용하지 않으려 고 노력했지만 차이점이 없습니다.

나는 vector.data()을 돌려 보았지만 새로운 벡터에 할당하는 것도 복사했습니다. .data() 메모리 블록에 대한 포인터를 유지하는 것은 원래 벡터의 크기를 조정해야하는 경우 매우 나쁜 생각입니다.

std::shared_ptr에서 벡터를 래핑하려고 시도했지만 shared_ptr에서 각 치수 벡터를 래핑 할 필요가 있음을 알았습니다.이 벡터는 지나치게 성가신 사실을 빠르게 나타냅니다.

나는 vector::iterator을 반환하는 제안을 보았습니다. 아직 그 일을 할 수 없었습니다. 어쩌면 2D 데이터를 얻는 것이 그 길을 걷고 있습니다. 나는 iterator를 검사 할 때 충돌없이 실행되도록 노력하고있다.

1D 배열을 사용하면이 문제를 해결할 수 있을지 모르지만 수백만 개의 호출에 대한 모든 색인 참조를 계산하는 것이 차선책으로 보입니다. std::array도 사용하는 것으로 생각했지만 벡터가 가장 간단한 변환으로 보입니다. 아마 나는 그것을 재고해야한다.

누구든지이 작업을 수행하는 방법에 대한 제안 사항이 있으면 알려 주시면 감사하겠습니다.

클래스 화학은 - 원래 행렬을 concentration

class chem 
    { 
    public: 
     typedef std::vector<float> fvec1D; 
     typedef std::vector<std::vector<float> > fvec2D; 

     chem(int xstep, int zstep) : concentration(xstep, fvec1D(zstep, 1.5)) {} 

     ... 

     const fvec2D &getConc() const { return concentration; } 
     const fvec1D &getConc(int x) const {return concentration[x]; } 

    private: 
     fvec2D  concentration; 
    }; 

클래스 모델을 관리 - 요구 chem::concentration

class model 
    { 
    public: 
     typedef std::vector<float> fvec1D; 
     typedef std::vector<std::vector<float> > fvec2D; 

    ... 

    private: 

     fvec2D  null2D {{0.0}}; 
     fvec1D  null1D {0.0}; 

     fvec2D  &outVar2D;// = null2D; // tried this and at ctor 
     fvec1D  &outVar1D;// = null1D; 


     std::vector<std::unique_ptr<chem> > chemList; 
    }; 

    model::model() : outVar2D(null2D), outVar1D(null1D) 
    { 
     outVar2D = chemList[0]->getConc();  // or 
     outVar1D = chemList[0]->getConc(1); 
    } 

    void model::plot() 
    { 
     for (int z=0; z<numZSteps; ++z) { 
      std::cout << outVar1D[z]; 
      std::cout << outVar2D[1][z]; 
     } 
    } 

    void model::run() 
    { 
     plot();    // produces init concentration of 1.5 at each z 

     chemList[0]->changeConc(); // Changes values in concentration 

     plot();    // STILL produces init conc of 1.5 at each z 
    } 
+0

TMI. 원하지 않는 동작을 보여줄 수있는 코드를 12 줄 이상 줄이십시오. –

+0

감사합니다. @ 샘. 내가 너무 멀리/충분하지 않은지 알려줘. – psimpson

+1

이것은 실제 코드가 아닌 가짜 코드이거나 깨진 C++ 컴파일러를 사용하고 있습니다. 그림과 같이 자기 존중 C++ 컴파일러는 컴파일하지 않습니다. 클래스에 참조 인 멤버가 있으면 생성자에서 초기화해야합니다. 'model :: model()'은 두 개의 참조 멤버를 초기화하지 못합니다. 생성자 본문의 할당은 초기화가 아닙니다 (초기화되지 않은 참조를 할당하여 메모리가 손상되어 결국 임의의 충돌이 발생합니다). 당신 사본이 있어요. –

답변

0

에 대한 액세스를 읽어 내 자신의 질문에 적절한 대답하면 나도 몰라 (알려 주시기 바랍니다). 나는이 문제가 자동 응답 될 것이라는 것을 알고 있으므로, 나는 이것을 해결할 수있는 가장 좋은 방법에 대한 제안을 아직도 듣고 있기 때문에 내가 가진 해결책을 제시 할 것이라고 생각했다. 나는 여전히 내가 C++ 프로그래밍 기술을 직관적으로 볼 수는 없다는 것을 알고있다.

내가 시도한 내용이 작동하지 않는다는 의견에서 모아서 shared_ptr에 내 벡터를 래핑했습니다. shared_ptr (다차원 공간 데이터 용 및 출력 변수 목록 용)의 두 레벨을 관리하기 위해 랩퍼 클래스를 작성했습니다. 또한 배열 유형의 인덱싱을 그대로 유지하고 동작을 operator=으로 정의합니다.

여기에 2D 클래스 만 포함되었습니다. 1D 및 3D 케이스도 처리 할 수있는 비슷한 클래스가 4 개 있습니다.

내가 게시 한 내용이 좋지 않다는 것을 안다. 그다지 우아하지 않아 각 차원의 케이스 (1D, 2D, 3D 데이터)마다 2 개의 클래스가 필요합니다. 템플릿을 사용하여 간단하게 만들 수 있습니다. 지금까지는 초등 템플릿 만 작성했습니다. 각 클래스는 (operator[]을 사용하여) 고유 한 클래스로 붕괴하기 때문에 템플릿이 도움이되는지 확실하지 않습니다.

키워드 배치를 모두 const 아직 알지 못했습니다. 컴파일러의 불만으로 좌절감을 느꼈습니다. 내가 시간을 내면 그걸 내려 줄거야.

나는 또한 복사 및 이동 생성자에 대해 어떤 종류의 동작을 원하는지 정확하게 알지 못하지만 벡터 크기 조정 작업을 위해 필요하다고 확신하지만 아직 구현하지 못했습니다. 나를 위해 중요한 것은 클래스간에 벡터에 대한 읽기 액세스 권한을 얻는 것이 었습니다. 따라서 벡터가 변경되면 내 출력 변수를 다시 파싱하지 않고 다른 곳에 반영됩니다.

#include <memory> 
    #include <vector> 

    namespace MDType { 
     class fpv2D; 

     typedef std::vector<float> fvec1D; 
     typedef std::vector<std::vector<float> > fvec2D; 
     typedef std::vector<std::vector<std::vector<float> > > fvec3D; 

     typedef std::shared_ptr<fvec1D> fvec1Dptr; 
     typedef std::shared_ptr<fvec2D> fvec2Dptr; 
     typedef std::shared_ptr<fvec3D> fvec3Dptr; 

     typedef std::vector<fpv2D> fvpv2D; 

     typedef std::shared_ptr<fvpv2D> fvpv2Dptr; 

     class fpv2D 
     { 
     public: 
      fpv2D(int x=1, int z=1, float fill=0.0) : theArray(new fvec2D(x, fvec1D(z, fill))) {} 

      fpv2D(const fpv2D &otherT) = default;  // Pretty sure this needs to change 

      fpv2D(fpv2D &&otherT) {theArray = otherT.data(); } 

      fvec2Dptr &data() { return theArray; } 

      fvec1D &operator[](int index) {return theArray->data()[index]; } 
      void operator=(fpv2D& rhs) { theArray = rhs.data(); } 

     private: 
      fvec2Dptr theArray; 
     }; 

     class fpvpv2D 
     { 
     public: 
      fpvpv2D(int index, int x=1, int z=1, float fill=0.0) : theArray(new fvpv2D(index, fpv2D(x, z, fill))) {} 

      fpvpv2D(const fpvpv2D &otherT) = default;  // Pretty sure this needs to change 

      fpvpv2D(fpvpv2D &&otherT) {theArray = otherT.data(); } 

      fvpv2Dptr &data() { return theArray; } 

      fpv2D &operator[](int index) {return theArray->data()[index]; } 
      void operator=(fpvpv2D& rhs) { theArray = rhs.data(); } 

     private: 
      fvpv2Dptr theArray; 
     }; 
    } 

... 그래서 ...

MDType::fpv2D  conc(numX, numZ, 1.5); 
    MDType::fpvpv2D  outVar2D(numOutVars, numX, numZ); 

    outVar2D[1] = conc; 
    cout << outVar2D[1][3][5];   // prints 1.5 
    conc[3][5] = 12.0; 
    cout << outVar2D[1][3][5];   // prints 12.0 
관련 문제