C++ “const std::any &”比没有 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 作为输入和输出)。在每个子类中,实际类型输入类型在编译时已知,因此我希望将 std::any 强制转换为特定类型。在上面的例子中,我只是使用一个函数来使其简单。
但是,使用 std::any
的函数调用构造函数和析构函数的次数比不使用 std::any 的函数多很多倍。上面的程序给出了以下输入:
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
的函数版本需要 3 个构造函数 + 2 个析构函数调用。而普通版本只需要 1 次构造函数调用。我假设 func 中的 return 语句是复制省略。
我该如何改进这个? 我需要的最重要的东西如下,如果 std::any
无法实现,请使用 std::variant
提供可能的解决方案。
MyVector
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
需要将对象复制到
std::any
中,因此尝试调用func_any(a)
将复制a
。您可以在
std::any
中保存std::reference_wrapper
或T*
指针:因为您已经知道什么实际上正在使用类型,您最好让基类使用
void*
作为输入和输出。您还可以
any_cast
参考type:这将是对 vec 中保存的值的引用(因此不涉及构造函数)。这不会减少副本总数,但会消除由于 NRVO 而导致的一招。
An object needs to be copied into the
std::any
, so trying to callfunc_any<int>(a)
will copya
.You can instead hold a
std::reference_wrapper<T>
or aT*
pointer in thestd::any
:Since you already know what types are actually being used, you might be better off making your base class use
void*
as input and output.You can also
any_cast
to a reference type:This will be a reference to the value held in
vec
(so no constructors involved). This will not reduce the overall number of copies, but it will get rid of one move due to NRVO.