复制作为参数传递的 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>
可能是更好的选择,对于稍大的 int
或 float
数组,但截止点在哪里或它是否真正重要尚不清楚。
但是您应该使用成员初始值设定项列表。您目前在代码中所做的是 分配 成员值。您没有使用传递的对象初始化它们。要真正 初始化 它们,你写:
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 位字,无论它是整个数组还是对它的引用(指针)。
事实上,使用引用甚至可能会在读取值时引入更多间接内存访问,从而稍微降低程序速度。
我一直在利用空闲时间开发一款使用 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>
可能是更好的选择,对于稍大的 int
或 float
数组,但截止点在哪里或它是否真正重要尚不清楚。
但是您应该使用成员初始值设定项列表。您目前在代码中所做的是 分配 成员值。您没有使用传递的对象初始化它们。要真正 初始化 它们,你写:
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 位字,无论它是整个数组还是对它的引用(指针)。
事实上,使用引用甚至可能会在读取值时引入更多间接内存访问,从而稍微降低程序速度。