![](/img/trans.png)
[英]Why does std::vector::emplace call destructor without any copy constructor called?
[英]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.