在这个C ++示例中,引用安全是否安全?

时间:2012-01-27 12:49:50

标签: c++

来自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 ++吗?

3 个答案:

答案 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存在,那么它应该是构造函数的参数,你不应该使用工厂函数。