对模板类 (N)RVO 优化调用的析构函数过多
Too many destructors called on template classes (N)RVO optimization
我正在尝试编写自己的智能指针(C++11)和堆栈,其中包含一个问题,可以用下一个示例来解释:
#include <iostream>
template<typename T_Type>
class TestTemplateClass {
private:
T_Type _state;
public:
TestTemplateClass() : _state() {
std::cout << "Default constructor" << std::endl;
}
TestTemplateClass(int inState) : _state(inState) {
std::cout << "State constructor" << std::endl;
}
template<typename T_OtherType>
TestTemplateClass(const TestTemplateClass<T_OtherType> &inValue) {
std::cout << "Template-copy constructor" << std::endl;
}
template<typename T_OtherType>
void operator = (const TestTemplateClass<T_OtherType> &inValue) {
std::cout << "Operator" << std::endl;
}
~TestTemplateClass() {
std::cout << "Destructor" << std::endl;
}
};
TestTemplateClass<int> createFunction() {
return TestTemplateClass<int>();
}
int main() {
TestTemplateClass<int> theReference = createFunction();
std::cout << "Finished" << std::endl;
return 0;
}
输出:
Default constructor
Destructor
Destructor
Finished
Destructor
如您所见,这里有很多析构函数。在我看来,这是复制 elision 和模板构造函数之间的交互问题,但我不知道这种错误的原因是什么。我试图通过添加复制构造函数并强制编译器使用我的模板构造函数来解决问题explicit
:
// After TestTemplateClass(int inState), but it's not important
explicit TestTemplateClass(const OwnType &inValue) {
std::cout << "Copy constructor" << std::endl;
}
得到下一个输出:
Default constructor
Template-copy constructor
Destructor
Template-copy constructor
Destructor
Finished
Destructor
这里看起来都不错,但看起来不像一个干净的解决方案。有更好的选择吗?
(N)RVO 永远不会在构造函数和析构函数调用的数量之间引入差异。它旨在使这基本上是不可能的。
问题出在您的代码上。根据语言规则,构造函数模板永远不会用于生成复制构造函数。复制构造函数从来都不是模板,句点。
因此,您的类模板实际上并没有声明复制构造函数,因此编译器会生成默认的构造函数(当然不会打印任何内容)。如果需要在复制构造函数中进行任何特殊处理,则必须始终手动声明它。模板永远不会用于实例化模板。
您的实验表明根本没有错误:第一个版本只是使用不打印任何内容的复制构造函数,而第二个版本使用不同的构造函数,因为您有效地禁用了它。
(看起来您使用的任何编译器和选项都不执行 RVO)
相关文章:
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- C++延迟后的优化器调用函数
- 对于优化级别为 0 的 std::vector,析构函数被调用两次
- 在循环条件中调用const vector size()似乎缺少优化
- C++编译器可以优化对 at() 的调用吗?
- 编译器 虚拟函数调用的优化
- 如何应用尾部调用优化
- 根据全局日志级别优化日志函数调用
- C++:优化析构函数调用
- 优化调用一系列功能指针
- 尾部调用优化是否适用于此功能?
- 对 constexpr 与内联函数的调用编译为不同的程序集,并禁用优化
- 为什么 noreturn/__builtin_unreachable 会阻止尾部调用优化
- 尾部调用优化似乎略微降低了性能
- 编译时,复制构造函数/复制分配和正常功能调用优化之间是否存在任何区别
- c++支持模板元编程中的最后调用优化
- Can-Tail调用优化与RAII共存
- 局部变量和尾部调用优化
- 针对以下情况的 GCC 尾调用优化