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
转换为特定类型。在上面的示例中,我只是使用一个函数来简化它。
但是,带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<T> res = any_cast<MyVector<T>>(vec); // I want res to const reference MyVector<T> vec, not copy
需要将对象复制到 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*
作为输入和输出。
您还可以any_cast
引用类型:
const MyVector<T>& res = std::any_cast<const MyVector<T>&>(vec)
这将是对 vec
中保存的值的引用(因此不涉及构造函数)。这样不会减少整体的份数,但是会因为NRVO去掉一招。
#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
转换为特定类型。在上面的示例中,我只是使用一个函数来简化它。
但是,带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<T> res = any_cast<MyVector<T>>(vec); // I want res to const reference MyVector<T> vec, not copy
需要将对象复制到 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*
作为输入和输出。
您还可以any_cast
引用类型:
const MyVector<T>& res = std::any_cast<const MyVector<T>&>(vec)
这将是对 vec
中保存的值的引用(因此不涉及构造函数)。这样不会减少整体的份数,但是会因为NRVO去掉一招。