简体   繁体   English

如何设计类对可以反弹的大对象的依赖?

[英]How to design class dependence on large objects which can be rebound?

where I need to change the internal variable to refer to new objects, then do something, then again change the object, and then do something on the new value. 我需要更改内部变量以引用新对象,然后执行某些操作,然后再次更改对象,然后对新值执行某些操作。

class dml
{
     void setTrain(matrix<T> train_x , matrix<T> train_y)
     {
          train_x_ = train_x;
          train_y_ = train_y;
     }
     void train();

     private:
          matrix<T> train_x_;
          matrix<T> train_y_;
}

So, I will first set train , then call train, which uses the values that I just set to train. 因此,我将首先设置train,然后调用train,它将使用我刚刚设置的值进行训练。 Then later on I might change the values, by calling setTrain on new values and I want to run train on that data again. 然后,稍后我可以通过对新值调用setTrain来更改值,而我想再次对该数据运行train。 ( For people from ML, I want to implement mini batches, where I feed in data, train on it, then feed in the next batch of data and then train on it) The simple solution that I have right now is stupid, as it involves the copying of a very large matrix. (对于来自ML的人们,我想实现迷你批处理,在其中输入数据,对其进行训练,然后输入下一批数据,然后对其进行训练。)我现在拥有的简单解决方案很愚蠢,因为它涉及复制非常大的矩阵。 I pointers are the easy solutions that come to mind, but I would prefer not to use them. 我的指针是想到的简单解决方案,但我不希望使用它们。 My program is pretty complex and pointers and mem allocation will only be more trouble. 我的程序非常复杂,指针和内存分配只会带来更多麻烦。 One Idea I though about is : 我的一个想法是:

     private:
          matrix<T>& train_x_;
          matrix<T>& train_y_;
}

Ofcourse this does not work, as reference cannot ever point to null value and I have to initialize them in the constructor and since they cannot be re-bound, there is no point in using them. 当然这是行不通的,因为引用永远不能指向null值,而我必须在构造函数中对其进行初始化,并且由于它们无法重新绑定,因此使用它们毫无意义。

I think the solution would be in using some of the smart pointers. 我认为解决方案将是使用一些智能指针。 But smart pointers are used to manage the memory in heap, but I am not allocating an memory in the heap. 但是智能指针用于管理堆中的内存,但是我没有在堆中分配内存。 The matrix object is created in the stack, but it is implemented using a std::vector, which initializes all of its objects in the heap. 矩阵对象是在堆栈中创建的,但是它是使用std :: vector实现的,它会初始化堆中的所有对象。

I think logically shared_ptr should work, as we are sharing a varaible. 我认为逻辑上shared_ptr应该起作用,因为我们正在共享一个变量。 std::make_shared seems to be a good idea, but I read that it too creates a copy when you try create a shared_ptr from an existing object in the stack. std::make_shared似乎是一个好主意,但我读到当您尝试从堆栈中的现有对象创建shared_ptr时,它也会创建一个副本。 But this does not solve the problem of having to copy such a large object. 但这不能解决必须复制这么大对象的问题。

Another obvious thing is std::move , but move does not apply here, as I might need to use the train data agian, outside of the function call. 另一个明显的东西是std::move ,但是move不适用于此处,因为我可能需要在函数调用之外使用train data agian。

I am certain that I am missing something obvious. 我确定我缺少明显的东西。 I am kind of sleep deprived right now, so any solutions would help me out a lot ! 我现在有点睡眠不足,因此任何解决方案都可以帮我很多忙!

Just to clarify: 只是澄清一下:

LargeObj a=9;
auto a_ptr=std::make_shared(a);

If I do this, then a_ptr will just point to a, without creating a copy? 如果我这样做,那么a_ptr只会指向a,而不创建副本? But this is not what one of the answer here says: 但这不是这里的答案之一:

Create a boost::shared_ptr to an existing variable 创建一个boost :: shared_ptr到现有变量

int a = 3; int a = 3; // Existing variable shared_ptr aCopy = make_shared(a); //现有变量shared_ptr aCopy = make_shared(a); //Create copy with value of a //创建一个值为a的副本

 LargeObj a=9; auto a_ptr=std::make_shared(a); 

If I do this, then a_ptr will just point to a, without creating a copy? 如果我这样做,那么a_ptr只会指向a,而不创建副本?

If you create a shared pointer by copying from an existing object (that allows it) then you will have two objects. 如果通过从现有对象(允许它)中进行复制来创建共享指针,则将有两个对象。 This can be avoided by deleting the relevant functions in the class and/or by not ever defining the object as anything other than a shared_ptr<matrix<T>> . 可以通过删除类中的相关功能和/或通过从未将对象定义为shared_ptr<matrix<T>>以外的任何方式来避免这种情况。


You can work with large objects and prevent copying if you use std::shared_ptr . 如果使用std::shared_ptr则可以处理大型对象并防止复制。

The following is an adaption of the example in the question. 以下是问题示例的改编。 It creates the objects as std::shared_ptr s and shows how they can be assigned to the class in the example. 它以std::shared_ptr的形式创建对象,并在示例中显示了如何将它们分配给类。

#include <memory>
#include <iostream>
#include <string>

template <typename T>
class matrix {
public:
    matrix() = default;
    matrix(const matrix&) = delete; // no copy
    matrix(matrix&&) = default; // allow move
    matrix& operator=(const matrix&) = delete; // no copy
    matrix& operator=(matrix&&) = default; // allow move
};

template <typename T>
class dml
{
public:
    void setTrain(std::shared_ptr<matrix<T>> train_x_ptr, std::shared_ptr<matrix<T>> train_y_ptr)
    {
        train_x_ = train_x_ptr;
        train_y_ = train_y_ptr;
    }
    void train() {};
private:
    std::shared_ptr<matrix<T>> train_x_{}; // starts out as an empty shared pointer (contains nullptr)
    std::shared_ptr<matrix<T>> train_y_{}; // starts out as an empty shared pointer (contains nullptr)
};

int main()
{
    // no explicit new, object is created on the heap (train_x_ptr is created on the stack,
    // but will be copied to dml without copying the underlying object).
    auto train_x_ptr{std::make_shared<matrix<int>>()}; 
    auto train_y_ptr{std::make_shared<matrix<int>>()};
    dml<int> d;
    d.setTrain(train_x_ptr, train_y_ptr);
}

Note that new is not used directly. 注意new不能直接使用。

I think the solution would be in using some of the smart pointers. 我认为解决方案将是使用一些智能指针。 But smart pointers are used to manage the memory in heap, but I am not allocating an memory in the heap. 但是智能指针用于管理堆中的内存,但是我没有在堆中分配内存。 The matrix object is created in the stack, but it is implemented using a std::vector, which initializes all of its objects in the heap. 矩阵对象是在堆栈中创建的,但是它是使用std :: vector实现的,它会初始化堆中的所有对象。

In this example the std::shared_ptr will create matrix on the heap and manage the lifetime for you. 在此示例中, std::shared_ptr将在堆上创建matrix并为您管理生存期。 At the same time, if matrix contains a std::vector those elements will also be on the heap somewhere, managed by std::vector . 同时,如果matrix包含std::vector这些元素也将在堆上某处,由std::vector管理。

I think logically shared_ptr should work, as we are sharing a varaible. 我认为逻辑上shared_ptr应该起作用,因为我们正在共享一个变量。 std::make_shared seems to be a good idea, but I read that it too creates a copy when you try create a shared_ptr from an existing object in the stack. std::make_shared似乎是一个好主意,但我读到当您尝试从堆栈中的现有对象创建shared_ptr时,它也会创建一个副本。 But this does not solve the problem of having to copy such a large object. 但这不能解决必须复制这么大对象的问题。

It will not create a copy. 它不会创建副本。 It does solve the problem. 它确实解决了问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM