2016-07-01 6 views
1
#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <map> 

class Car { 
public: 
    Car(float costs, float speed) : costs(costs), speed(speed){}; 

    float getSpeed() const { 
     return speed; 
    } 

    float getCosts() const { 
     return costs; 
    } 

private: 
    float costs; 
    float speed; 
}; 


class CarManager { 
public: 

    CarManager(){}; 

    void assignCars(std::vector<Car> &cars){ 
     float costs = 1000.0; 

     float inc_costs = 700.0; 
     float inc_speed = 50.0; 

     for (size_t i = 0; i <= 10; ++i) { 
      float speed = 10.0; 
      std::vector<Car*> car_vec; 
      for (size_t j = 0; j < 5; ++j) { 

       if (j >= i) { 
        cars.push_back(Car(costs, speed)); 
        car_vec.push_back(&cars.back()); 
       } 
       speed += inc_speed; 
      } 

      car_storage.insert({costs , car_vec } ); 
      costs += inc_costs; 
     } 
    } 

    void print(){ 
     for (const auto & p : car_storage) { 
      std::cout << "map[" << p.first << "] = "; 
      for (const auto & s : p.second) { 
        std::cout << "[" << s->getSpeed() <<", " << s->getCosts() << "] , "; 
      } 
      std::cout << std::endl; 
     } 
    } 

private: 
    std::map<float, std::vector<Car*> > car_storage; 
}; 

int main() 
{ 

    std::vector<Car> cars; 
    CarManager car_manager; 
    car_manager.assignCars(cars); 
    car_manager.print(); 

} 

printout은 내가 예상 한 것과 다소 차이가 있습니다. 비용과 속도를 가진 자동차를 벡터 [cars.push_back(Car(costs, speed))]에 넣고 나중에 Car* : car_vec.push_back(&cars.back())의 로컬 벡터에서이 Car에 대한 포인터를 누릅니다. 다음으로 키 (costs)와 값 (car_vec)을 맵에 삽입합니다. 지도를 인쇄 할 때 값이 올바르지 않습니다. 예를 들어 첫 번째 경우 지도 삽입이 개체 멤버 값을 변경하는 이유는 무엇입니까?

: 1 루프 i = 0 따라서 j 내부 루프는 (j> = 1) 및 I는를 Car(1000.0, 10.0)와 push_back. 지도에 포함 된 내용은 나중에 Car(0,0)입니다. 다른 자동차의 경우에도 마찬가지로 적용되지만 이상한 가치가 있습니다.

map[1000] = [0, 0] , [0, 7.41086e-38] , [0, 7.41063e-38] , [0, 7.41064e-38] , [210, 1700] , 

map[1700] = [0, 7.41092e-38] , [0, 7.41094e-38] , [0, 7.41094e-38] , [210, 1700] , 

map[2400] = [110, 2400] , [160, 2400] , [210, 2400] , 

map[3100] = [160, 3100] , [210, 3100] , 

map[3800] = [210, 3800] , 

실마리가 없습니다. 디버깅을 통해 값이 car_storage.insert({costs , car_vec } )에 맵에 삽입 될 때까지 확인 된 것으로 나타났습니다.

답변

2

이 쓸 때 어떻게됩니까 :

cars.push_back(Car(costs, speed)) 
car_vec.push_back(&cars.back()) 

를? Car을 만들고 복사본cars 벡터에 푸시합니다. 다음 줄에서이 벡터의 복사본에 포인터를 푸시합니다. 절대하지 마! 첫 번째 벡터의 크기가 push_back, clear 등으로 변경되면 모든 내용을 다시 할당 할 수 있습니다. 나는. 그것은 새로운 메모리 조각을 취하고, 거기에 값을 복사하고, 이전 값을 삭제합니다. 이전 내용의 내용이 유효하지 않게됩니다.

+0

좋아, 나는 복사본이 푸시된다고 몰랐다. 나는 C++ 11 이후에'std :: move()'가 수행 될 것이라고 생각했다. 수정 후 emplace_back을 사용하겠습니까? 아니면 어떻게 해결할 수 있을까요? –

+1

@SeanM. 'emplace_back'은 복사하지 않고 객체를 생성 할 수있게합니다. 그러나'cars.back()'의 주소는 언제든지 바뀔 수 있습니다. 어쩌면 좋은 방법은 포인터 벡터를 유지하는 것입니다. 그것은 아마도 "무거운"사용자 클래스를위한 포인터 벡터를 유지하는 좋은 형태가 될 것입니다. 수동으로 메모리를 관리하지 않으려면 _vector <[unique_ptr] (http://www.cplusplus.com/reference/memory/unique_ptr/?kw=unique_ptr) _ _ 또는 _vector <[shared_ptr] (http : //www.cplusplus.com/reference/memory/shared_ptr/?kw=shared_ptr)>_. – ilotXXI

+1

@SeanM. 이 코드에서 임시 객체는 C++ 11 이후에 _moved_ 될 것입니다. 그러나 나는 그것이이 수업에 어떤 차이가 있다고 생각하지 않는다. 어쨌든 문제는 사본이 아닙니다. 주소 변경 또는 로컬 변수에 대한 포인터입니다. – ilotXXI

관련 문제