复制作为参数传递的 std::array 的最佳方法是什么?

What is the best way to copy a std::array passed as a parameter?

我一直在利用空闲时间开发一款使用 C++ 和 SDL2 编写的游戏,并且正在为可绘制对象改进我的一些基础 classes。这些对象具有位置(x 和 y)和大小(宽度和高度)。将这些对象存储在固定大小的数组中对我来说更有意义,因此我一直在使用 std::array 将这些值包含在我的 class 中,因为长度是固定的。我对如何复制作为参数传递给构造函数的 std::array 有点困惑(在我的 setter 方法中也是如此)

我现在就是这样

class Drawable {
    protected:
        std::array<float, 2> position;                                 
        std::array<int, 2> drawsize;                                   
        SDL_Texture * texture;
    public:
        // constructor                                               
        Drawable(const std::array<float, 2> pos, const std::array<int, 2> size, SDL_Texture* text);

        // setters
        void set_pos(const std::array<float, 2> &pos) { position = pos; }
        void set_size(const std::array<int, 2> &size) { objsize = size; }
};

Drawable::Drawable(const std::array<float, 2> &pos, const std::array<int, 2> &size, SDL_Texture* text) {
    position = pos; // like this?
    objsize = size; // ???

    texture = text;
}

我从上面省略了很多不必要的细节 class 以专注于我要问的主要问题

我很困惑,因为我读到你可以通过赋值复制 std::array(所以 std::array<int, 5> arr2 = arr1;),但我不确定当你将数组作为像我一样不断参考(const std::array<int, 2> &arr)。因为无论如何我都在复制数组,所以通过常量引用传递数组是否有意义?由于它们的长度只有2,我曾考虑过将每个元素复制到成员变量中,但如果有更易读的解决方案,我欢迎。

我对 C++ 和标准库中的容器比较陌生。这主要是为了多学习,玩得开心:^)

无论哪种方式,通过引用或通过值,都可以。

但不要手动分配单个元素。这正是 std::array 的 assignment/constructor 为您所做的。

一般来说,copied/moved 到 class 成员的构造函数参数应该按值还是按引用传递是一个更复杂的话题(有利有弊) both) 我认为如果你是语言新手,你应该不会太在意。

我想说的是,在您了解 移动语义 之前,暂时坚持通过 const 参考传递,这将为您提供为什么按值传递可能是有用。但对此的看法会有所不同。我这么说主要是因为它与有关传递其他非标量类型的建议更加一致。

如果您只是按值传递(不添加您可能还不知道的 std::move),那么您将制作 两个 副本目的。一个用于在构造函数中构造参数,一个用于 construct/assign 成员。当然,编译器很可能会优化其中之一,无论如何,假设构造函数是内联的并且类型很简单。 (在 std::array<float, ...> 的情况下,这里是否使用 std::move 甚至都没有关系。)

还有一个论点是,在某些情况下,通过引用传递小对象在性能方面可能比通过值传递小对象更差,但同样,如果您是新手,这不应该让您担心语言。无论如何,这将取决于特定情况,并且何时效率更高以及何时效率更低并不明显。在大多数情况下,编译器可能会将任一变体优化为相同的代码(再次假设构造函数可以内联)。

从性能的角度来看,按值传递 std::array<int,2>std::array<float,2> 可能是更好的选择,对于稍大的 intfloat 数组,但截止点在哪里或它是否真正重要尚不清楚。


但是您应该使用成员初始值设定项列表。您目前在代码中所做的是 分配 成员值。您没有使用传递的对象初始化它们。要真正 初始化 它们,你写:

Drawable::Drawable(const std::array<float, 2> &pos, const std::array<int, 2> &size, SDL_Texture* text)
    : position(pos),
      objsize(size),
      texture(test) {
}

其中成员必须(理论上 应该)按照它们在 class.

中声明的顺序列出

std::array<float, 2>std::array<int, 2> 的情况下,没有理由忽略 const &。通过 const & 的目的是防止 expensive/unnecessary 复制。但这里没有什么贵的。在我的 64 位机器上,sizeof std::array<float, 2>std::array<int, 2> 或任何引用(底层是指针)都是 8。因此,您只是复制一个 64 位字,无论它是整个数组还是对它的引用(指针)。

事实上,使用引用甚至可能会在读取值时引入更多间接内存访问,从而稍微降低程序速度。