C++ C++;按值传递/按引用函数重载

C++ C++;按值传递/按引用函数重载,c++,c++11,C++,C++11,有两个函数重载: 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 overl

有两个函数重载:

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

另外,它不是用于实际程序,只是我自己检查传递参数、返回值以及它们以不同方式的行为的差异,并且所有函数都具有相同的名称:

// 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;
}
//按值传递(复制)
MyClass做某事(MyClass参数){
库特
是否有任何特殊的方法来显式指定参数是通过值传递还是通过引用传递

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

是否有任何特殊的方法来显式指定参数是通过值传递还是通过引用传递

没有,但有解决办法

  • 使用模板方法和专门化,您可以明确地告诉您想要的版本:

    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;
    }
    

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

struct MyClass{char const*s;};
MyClass做某事(MyClass){返回MyClass();}
const MyClass&do_something(const MyClass¶m){return param;}
auto main()->int
{
MyClass c1{“c1”};
static_cast(do_something)(c1);//值重载
静态_cast(do_something)(c1);//Ref重载
}
但是在实践中,您应该只是以不同的方式命名函数,或者使用打破僵局的参数或参数类型,即设计函数以明确选择函数


我会给他们起不同的名字,因为他们做不同的事情,所以这表明他们做了错误的事情™ 使用相同的名称。

这是不可能的,也没有任何意义。如果每次都需要指明要使用哪一个重载函数,则无法达到重载的目的。如果所讨论的函数是模板,而MyClass是模板参数,则可以根据MyClass是否可复制来消除结果的歧义。@n。m、 他说,他完全忽略了移动语义。也许你应该先测试你的假设。对,这样就不能消除两个重载之间的歧义。这只会导致一个编译器错误。模板是件好事。第二个选项——重命名函数会更简单。但作为一个选项——也应该起作用。Thanks!
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;
}
do_something(c, by_value{}); // value
do_something(c, by_ref{}); // reference
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
}