Избегайте векторной копии c ++ - PullRequest
0 голосов
/ 30 октября 2019

Я хочу избежать создания копий вектора, который достаточно велик. Вот довольно четкий пример того, в чем проблема:

struct MyStruct {
    std::vector<int> v;
    int x;
}

class MyClass {
    MyStruct lastStruct_;
public:
    MyStruct create_struct() {
        MyStruct s = { std::vector<int>(1000000, 1), 1234 };
        lastStruct_ = s;  // THIS IS A FULL COPY, PROBLEM
        return s; // THIS SHOULD NOT BE A COPY AS PER C++11 AND UP
    }
    MyStruct getLastStruct() {
            return lastStruct_;
    }
}

void main()
{
    MyClass c;
  for (int i = 0; i < A_LOT; i++)
  {
    writeToDisk(c.create_struct());
  }
  //MEANWHILE IN OTHER THREAD:
  // while(true)
  //   updateUI(c.getLastStruct());
}

Как мне избежать копирования здесь? Я пытаюсь решить эту проблему с помощью общих указателей, но я все еще новичок в этом. Будет ли что-то вроде этой работы (синтаксис может быть выключен)?

struct MyStruct {
    std::vector<int> v;
    int x;
}

class MyClass {
    std::shared_ptr<MyStruct> lastStruct_;
public:
    MyStruct create_struct() {
        auto s = std::maked_shared<MyStruct>({ std::vector<int>(1000000, 1), 1234 });
        lastStruct_ = s;
        return *s; 
    }
    std::shared_prt<MyStruct> getLastStruct() {
            return lastStruct_;
    }
}

void main()
{
    MyClass c;
  for (int i = 0; i < A_LOT; i++)
  {
    writeToDisk(c.create_struct());
  }
  //MEANWHILE IN OTHER THREAD:
  // while(true)
  //   updateUI(c.getLastStruct()->data());
}

1 Ответ

1 голос
/ 30 октября 2019

Вот наиболее очевидный способ:

struct MyStruct {
    std::vector<int> v;
    int x;
}

class MyClass {
    std::shared_ptr<MyStruct> lastStruct_;
public:
    std::shared_ptr<const MyStruct> create_struct() {
        auto s = std::maked_shared<MyStruct>({ std::vector<int>(1000000, 1), 1234 });
        // acquire lock
        lastStruct_ = s;
        // release lock
        return s; 
    }
    std::shared_ptr<const MyStruct> getLastStruct() {
        // acquire lock
        auto j = lastStruct_;
        // release lock
        return j;
    }
}

void main()
{
  MyClass c;
  for (int i = 0; i < A_LOT; i++)
  {
    auto j = c.create_struct();
    writeToDisk(*j);
  }
  //MEANWHILE IN OTHER THREAD:
  // while(true)
  // {
  //   auto j = c.getLastStruct();
  //   updateUI(j->data());
  // }
}

Обратите внимание, что мы заменяем объект, заменяя общий указатель на старый объект общим указателем на новый объект. Код, который обращается к старому объекту, сохраняет его в силе до тех пор, пока с ним не будет покончено.

Вам необходим какой-то тип блокировки, чтобы защитить lastStruct_ от изменения в одном потоке, когда к нему обращаются в другом потоке.

...