C ++传递值/通过引用函数重载

时间:2015-06-28 07:18:55

标签: c++ c++11

有2个函数重载:

MyClass do_something(MyClass param);
const MyClass& do_something(const MyClass& param);

然后我这样做:

MyClass c1 {"c1"};
do_something(c1);  // I want this to be used by value overload
do_something(c1);  // this to be used by reference overload

是否有任何特殊方法可以显式指定参数是按值传递还是按引用传递?

对于移动语义,std::move()我想知道我的案例中是否有std::copy() std::ref这样的内容?

P.S。它不是用在真实的程序中,只是自己检查传递参数的差异,以不同的方式返回值和它们的行为,并使所有函数具有相同的名称:

// pass by value (copy)
MyClass do_something(MyClass param) {
    cout << "do_something(MyClass param)" << endl;
    param.i = 100;
    return param;
}

// !!! Your normal habit when passing an argument to a function should be to pass by const reference. (thinking in c++)
// pass by reference (reference)
const MyClass& do_something(const MyClass& param) { // doesn't allow to modify the object
    cout << "do_something(MyClass& param)" << endl;
    return param;
}

// pass by move semantic (move)
MyClass&& do_something(MyClass&& param) {
    cout << "do_something(MyClass&& param)" << endl;
    param.name += "__after_do_something(MyClass&& param)";
    param.i = 100;
    return move(param);
}

// pass by pointer (reference)
MyClass* do_something(MyClass* const param) { // allows to modify object, but not pointer (address)
    cout << "do_something(MyClass* const param)" << endl;
    param->i = 100;
    // (*param).i = 100;  // the same as above
    return param;
}

3 个答案:

答案 0 :(得分:2)

  

是否有任何特殊方法可以显式指定参数是按值传递还是按引用传递?

不,但有解决方法。

  • 使用模板方法和专业化,您可以明确告诉您需要哪个版本:

    class QQQ {
       public function www($x) {
          echo $x;
       }
    }
    
    $q = 'QQQ';
    $w = 'www';
    
    $q::$w(7); // this is what I am trying to do but it throws an error.
    

    然后叫它:

    template <typename T>
    T do_something(T);
    
    template<>
    MyClass do_something(MyClass) { std::cout << "value" << std::endl; }
    
    template<>
    const MyClass& do_something(const MyClass&)
    {
        std::cout << "reference" << std::endl;
    }
    

    Live Demo

  • 但使用显式标记创建重载会更简单/更清晰:

    do_something<MyClass>(c); // value
    do_something<const MyClass&>(c); // reference
    do_something(c); // value
    

    并称之为

    struct by_value{};
    struct by_ref{};
    
    MyClass do_something(MyClass, by_value) { std::cout << "value" << std::endl; }
    
    const MyClass& do_something(const MyClass&, by_ref)
    {
        std::cout << "reference" << std::endl;
    }
    

答案 1 :(得分:1)

您可以通过转换为相关的函数指针类型来解决过载歧义(这是表达式类型由外部上下文确定而不是从内部构建的极少数情况之一):

struct MyClass { char const* s; };

MyClass do_something(MyClass) { return MyClass(); }
const MyClass& do_something(const MyClass& param) { return param; }

auto main() -> int
{
    MyClass c1 {"c1"};
    static_cast<MyClass(*)(MyClass)>( do_something )( c1 );         // Value overload
    static_cast<MyClass const&(*)(MyClass const&)>( do_something )( c1 );  // Ref overload
}

但实际上你应该用不同的方式命名函数,或者使用tie-breaker参数或参数类型,即设计显式函数选择的函数。

我会以不同的名称命名它们,因为它们做了不同的事情,因此它表明错误的东西™具有相同的名称。

答案 2 :(得分:-2)

  

是否有任何特殊方法可以明确指定参数是通过值还是通过引用传递的?

是。如果它不可复制(即删除或私有复制构造函数),则只能通过引用传递。