来自Java我想在C ++中实现以下“测试多个实现”的习惯用法
void testMethod() {
List veryBigList = createNewRandomList(10000);
Algo algo = createAlgo(veryBigList);
algo.run();
}
// this can be overwritten from a subclass to test against different algo
Algo createAlgo(List list) {
Algo a(list);
return a;
}
List createNewRandomList(int size) {
List l = new ArrayList(size);
// fill list with random objects
return l;
}
我有点迷失如何在C ++中以正确的方式做到这一点...当我这样做时:
void test_method() {
vector<string> big_list(10000);
init_random_list(big_list);
algo my_algo = create_algo(big_list);
my_algo.run();
}
algo create_algo(vector<string> list) {
algo a(list);
return a;
}
void init_random_list(vector<string> list) {
// fill list with random objects
}
然后C ++会做什么?它会复制完整列表去create_algo然后返回它会复制算法(和列表再次)?
但是当通过引用使用call时,我会访问algo范围之外的test_method中的引用,这会导致很多麻烦并违反RAII原则,对吗?
我知道对于C ++的一些实现,它们根据this doc优化了按值调用的速度,但是我可以依赖它来获取g ++和visual c ++吗?
答案 0 :(得分:2)
假设代码与您发布的完全一致,并且可以修改algo
以存储引用,那么您可能希望传递并存储引用。
答案 1 :(得分:0)
首先,为什么不绕过algo my_algo(biglist)
的来电,在test_method
中拨打create_algo
?
但是,是的,你是对的,这将创建副本(原则上,虽然在实践中它可能不会,如果你很幸运)。所以真正的问题是,你在算法中做了什么?例如。如果您将列表视为只读,则使用引用很好。
如果没有,只需将调用更改为create_algo即可使用引用将阻止一个(潜在)副本。
答案 2 :(得分:0)
algo
的语义似乎有点不同寻常。它看起来像一个仿函数类,你在构造时传递和存储一个参数。大多数情况下,C ++仿函数类都是无状态的。
我认为做
更为规范std::function< algo_result( algo_args ) > // return generic functor type
create_algo(std::vector<std::string> &list) {
return std::bind( algo(), std::ref( list ) ); // store reference
// result of std::bind implicitly converts to std::function
}
std::bind
返回有状态仿函数对象,它与std::ref
一起使用,允许您在该对象内保留引用,而无需手动定义引用的存储方式。现在algo
对象和引用被复制到std::function
中,但这应该很便宜。
另一方面,如果algo
确实是有状态的并且需要list
存在,那么它应该是构造函数的参数,你不应该使用工厂函数。