链接时如何取消副本?

DDa*_*iel 10 c++ c++14 c++17

我正在创建一个链接类型的类,例如下面的小示例。似乎在链接成员函数时,将调用复制构造函数。有没有办法摆脱复制构造函数调用?在下面的玩具示例中,很明显,我只在处理临时工,因此“应该”(也许不是按照标准,而是从逻辑上)是一种省略。第二个最好的选择是复制省略,它是调用move构造函数的,但事实并非如此。

class test_class {
    private:
    int i = 5;
    public:
    test_class(int i) : i(i) {}
    test_class(const test_class& t) {
        i = t.i;
        std::cout << "Copy constructor"<< std::endl;
    }
    test_class(test_class&& t) {
        i = t.i;
        std::cout << "Move constructor"<< std::endl;
    }
    auto& increment(){
        i++;
        return *this;
    }
};
int main()
{
    //test_class a{7};
    //does not call copy constructor
    auto b = test_class{7};
    //calls copy constructor
    auto b2 = test_class{7}.increment();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:一些澄清。1.这不取决于优化级别。2.在我的实际代码中,我有比ints更复杂(例如,分配堆)的对象

lub*_*bgr 7

  1. 部分答案(它没有b2就位构造,但是将副本构造转变为移动构造):您可以increment在关联实例的值类别上重载成员函数:

    auto& increment() & {
        i++;
        return *this;
    }
    
    auto&& increment() && {
        i++;
       return std::move(*this);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这导致

    auto b2 = test_class{7}.increment();
    
    Run Code Online (Sandbox Code Playgroud)

    进行移动构造,b2因为test_class{7}它是临时的,并且调用的&&重载test_class::increment

  2. 对于真正的就地构造(即甚至不是移动构造),您可以将所有特殊和非特殊成员函数转换为constexpr版本。那你就可以

    constexpr auto b2 = test_class{7}.increment();
    
    Run Code Online (Sandbox Code Playgroud)

    而您既不需要搬家,也不需要复制结构。显然,对于简单的test_class,但对于不允许constexpr成员函数的更一般的情况,这是可行的。