我有一个函数,它接受一个数字并返回那么多东西(比方说,整数).什么是最干净的界面?一些想法:
vector<int>
.矢量将被复制多次,这是低效的.vector<int>*
.我的getter现在必须分配向量本身以及元素.有谁必须释放向量的所有常见问题,你不能分配一次并使用相同的存储器来进行对getter的许多不同调用等.这就是为什么STL算法通常避免分配内存,而是想要它传入了.unique_ptr<vector<int>>
.现在很清楚是谁删除了它,但我们还有其他问题.vector<int>
作为参考参数.getter可以push_back()
和调用者决定是否到reserve()
空间.但是,如果传入vector
非空,那么getter应该怎么做?附加?通过先清除它来覆盖?断言它是空的?如果函数的签名只允许一个解释,那将是很好的.begin
和end
迭代器.现在我们需要返回实际写入的项目数(可能小于预期),并且调用者需要注意不要访问从未写入的项目.iterator
,呼叫者可以通过insert_iterator
.char *
.:)And*_*owl 37
在C++ 11中,标准容器支持移动语义,您应该使用选项1.
它使你的函数的签名清晰,传达你只想要返回一个整数向量,并且它将是有效的,因为不会发出任何副本:std::vector
将调用移动构造函数(或者,很可能,命名返回将应用值优化,导致无移动且无副本):
std::vector<int> foo()
{
std::vector<int> v;
// Fill in v...
return v;
}
Run Code Online (Sandbox Code Playgroud)
这样您就不必处理诸如所有权,不必要的动态分配以及其他只是污染问题简单性的问题:返回一堆整数.
在C++ 03中,您可能希望使用选项4并对非const
向量进行左值引用:C++ 03中的标准容器不支持移动,并且复制向量可能很昂贵.从而:
void foo(std::vector<int>& v)
{
// Fill in v...
}
Run Code Online (Sandbox Code Playgroud)
但是,即使在这种情况下,您也应该考虑这种惩罚对您的用例是否真的重要.如果不是,您可能会选择更清晰的功能签名,但会牺牲一些CPU周期.
此外,C++ 03编译器能够执行命名返回值优化,因此即使理论上临时应该从您返回的值进行复制构造,实际上也不会发生复制.
Use*_*ess 11
你自己写的:
...这就是为什么STL算法通常会避免分配内存,而是希望它传入
除了STL算法不一般"想记忆通过",他们对迭代器操作来代替.这特别是为了将算法与容器分离,从而产生:
通过返回输入迭代器,将值生成与这些值的使用和存储分离.
最简单的方法是使用boost::function_input_iterator
,但下面是草图机制(主要是因为我输入的速度比思考速度快).
(使用C++ 11,但您可以用std::function
函数指针替换或只是硬编码生成逻辑):
#include <functional>
#include <iterator>
template <typename T>
class Generator: public std::iterator<std::input_iterator_tag, T> {
int count_;
std::function<T()> generate_;
public:
Generator() : count_(0) {}
Generator(int count, std::function<T()> func) : count_(count)
, generate_(func) {}
Generator(Generator const &other) : count_(other.count_)
, generate_(other.generate_) {}
// move, assignment etc. etc. omitted for brevity
T operator*() { return generate_(); }
Generator<T>& operator++() {
--count_;
return *this;
}
Generator<T> operator++(int) {
Generator<T> tmp(*this);
++*this;
return tmp;
}
bool operator==(Generator<T> const &other) const {
return count_ == other.count_;
}
bool operator!=(Generator<T> const &other) const {
return !(*this == other);
}
};
Run Code Online (Sandbox Code Playgroud)
(同样,用C++ 98的外联函数替换lambda是微不足道的,但是这样输入更少)
#include <random>
Generator<int> begin_random_integers(int n) {
static std::minstd_rand prng;
static std::uniform_int_distribution<int> pdf;
Generator<int> rv(n,
[]() { return pdf(prng); }
);
return rv;
}
Generator<int> end_random_integers() {
return Generator<int>();
}
Run Code Online (Sandbox Code Playgroud)
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
using namespace std;
vector<int> out;
cout << "copy 5 random ints into a vector\n";
copy(begin_random_integers(5), end_random_integers(),
back_inserter(out));
copy(out.begin(), out.end(),
ostream_iterator<int>(cout, ", "));
cout << "\n" "print 2 random ints straight from generator\n";
copy(begin_random_integers(2), end_random_integers(),
ostream_iterator<int>(cout, ", "));
cout << "\n" "reuse vector storage for 3 new ints\n";
out.clear();
copy(begin_random_integers(3), end_random_integers(),
back_inserter(out));
copy(out.begin(), out.end(),
ostream_iterator<int>(cout, ", "));
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1794 次 |
最近记录: |