繁体   English   中英

C++ "const std::any &" 比没有 std::any 时更多的复制构造函数调用

[英]C++ "const std::any &" more copy constructor call than without std::any

#include <iostream>
#include <vector>
#include <string>
#include <any>
using namespace std;

template <typename T>
class MyVector {
private:
    int n;
    T* data;
public:
    MyVector() {
        n = 0;
        data = nullptr;
        cout << "MyVector default constructor\n";
    }

    MyVector(int _n) {
        n = _n;
        data = new T[n];
        cout << "MyVector param constructor\n";
    }

    MyVector(const MyVector& other) {
        n = other.n;
        data = new T[n];
        for (int i=0; i<n; i++) data[i] = other.data[i];
        cout << "MyVector copy constructor\n";
    }

    MyVector(MyVector&& other) {
        n = other.n;
        data = other.data;
        other.n = 0;
        other.data = nullptr;
        cout << "MyVector move constructor\n";
    }

    MyVector& operator = (const MyVector& other) {
        if (this != &other) {
            n = other.n;
            delete[] data;
            data = new T[n];
            for (int i=0; i<n; i++) data[i] = other.data[i];
        }
        cout << "MyVector copy assigment\n";
        return *this;
    }

    MyVector& operator = (MyVector&& other) {
        if (this != &other) {
            n = other.n;
            delete[] data;
            data = other.data;
            other.n = 0;
            other.data = nullptr;
        }
        cout << "MyVector move assigment\n";
        return *this;
    }

    ~MyVector() {
        delete[] data;
        cout << "MyVector destructor: size = " << n << "\n";
    }

    int size() {
        return n;
    }
};

template <typename T>
any func_any(const any &vec) {
    cout << "\nBefore func_any assignment\n";
    MyVector<T> res = any_cast<MyVector<T>>(vec); // I want res to const reference MyVector<T> vec, not copy
    cout << "\nAfter func_any assignment\n";
    return res;
}

template <typename T>
MyVector<T> func(const MyVector<T> &vec) {
    cout << "\nBefore func assignment\n";
    MyVector<T> res = vec;
    cout << "\nAfter func assignment\n";
    return res;
}

int main()
{
    MyVector<int> a(5);
    MyVector<int> a2(6);
    cout << "-----------";

    cout << "\nBefore func_any call\n";
    auto b = func_any<int>(a);
    cout << "\nAfter func_any call\n";
    cout << "--------------";

    cout << "\nBefore func call\n";
    auto c = func<int>(a2);
    cout << "\nAfter func call\n";

    cout << "-----------------";
    cout << "\nBefore exit\n";
    return 0;
}

我正在尝试使用 Python 之类的接口(使用std::any作为输入和输出)创建一个函数执行器基 class。 在每个孩子 class 中,实际类型输入类型在编译时是已知的,因此我希望将std::any强制转换为特定类型。 在上面的示例中,为了简单起见,我只使用了 function。

但是,带std::any的 function 调用构造函数和析构函数的次数比不带的 function 多很多次。 上面的程序给出了以下输入:

MyVector param constructor
MyVector param constructor
-----------
Before func_any call
MyVector copy constructor

Before func_any assignment
MyVector copy constructor

After func_any assignment
MyVector move constructor
MyVector destructor: size = 0
MyVector destructor: size = 5

After func_any call
--------------
Before func call

Before func assignment
MyVector copy constructor

After func assignment

After func call
-----------------
Before exit
MyVector destructor: size = 6
MyVector destructor: size = 5
MyVector destructor: size = 6
MyVector destructor: size = 5

所以使用std::any的 function 版本需要 3 次构造函数 + 2 次析构函数调用。 而普通版本只需要 1 次构造函数调用。 我假设func中的return语句是复制省略。

我该如何改进呢? 我需要的最重要的东西在下面,如果std::any不可能,那么请提供一个可能的解决方案std::variant

MyVector<T> res = any_cast<MyVector<T>>(vec); // I want res to const reference MyVector<T> vec, not copy

需要将 object 复制到std::any中,因此尝试调用func_any<int>(a)将复制a

您可以改为在std::any中持有std::reference_wrapper<T>T*指针:

template <typename T>
any func_any(const any &vec) {
    cout << "\nBefore func_any assignment\n";
    MyVector<T> res = any_cast<std::reference_wrapper<const MyVector<T>>>(vec);
    cout << "\nAfter func_any assignment\n";
    return res;
}

auto b = func_any<int>(std::cref(a));

由于您已经知道实际使用了哪些类型,因此最好让您的基数 class 使用void*作为输入并使用 output。


您还可以any_cast转换为引用类型:

const MyVector<T>& res = std::any_cast<const MyVector<T>&>(vec)

这将是对vec中保存的值的引用(因此不涉及构造函数)。 这不会减少总份数,但会因为 NRVO 而摆脱一招。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM