c++ - 链接时如何删除拷贝?

标签 c++ c++14 c++17

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

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

编辑:一些澄清。 1. 这与优化级别无关。 2.在我的真实代码中,我有比 int 更复杂的对象(例如堆分配)

最佳答案

  1. 部分答案(它不会就地构造b2,而是将复制构造转变为移动构造):您可以重载increment成员函数关联实例的值类别:

    auto& increment() & {
        i++;
        return *this;
    }
    
    auto&& increment() && {
        i++;
       return std::move(*this);
    }
    

    这会导致

    auto b2 = test_class{7}.increment();
    

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

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

    constexpr auto b2 = test_class{7}.increment();
    

    您既不需要支付移动费用,也不需要支付复制费用。显然,这对于简单的 test_class 是可能的,但对于不允许 constexpr 成员函数的更一般的场景来说是不可能的。

关于c++ - 链接时如何删除拷贝?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58657371/

相关文章:

C++ 模板元编程

c++ - 在 C++ 中从键盘完成 cin

C++ : How can I solve a first-chance exception caused at an unknown point?

c++ - 自动扣除别名模板和模板类的模板参数

c++ - boost::remove_if 导致错误(只读变量不可赋值)

c++ - 如果未明确说明大小信息,模板函数如何知道大小?

c++ - 对齐输出中的小数位?

c++ - 我可以使用reduce代替for循环吗?

c++ - std::launder、std::vector 和 move 仅可构造类型

c++ - 为什么不支持连接 std::string 和 std::string_view?