C++ 模板类(N)RVO优化中调用的析构函数过多

C++ 模板类(N)RVO优化中调用的析构函数过多,c++,templates,c++11,copy-elision,C++,Templates,C++11,Copy Elision,我试图用一个问题编写自己的智能指针(C++11)和堆栈,这可以通过下一个示例来解释: #include <iostream> template<typename T_Type> class TestTemplateClass { private: T_Type _state; public: TestTemplateClass() : _state() { std::cout << "Default constructor"

我试图用一个问题编写自己的智能指针(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;
}
正如你所看到的,这里有很多析构函数。在我看来,复制省略和模板构造函数之间的交互存在一些问题,但我不知道这类错误的原因是什么。我试图通过添加
显式
复制构造函数并强制编译器使用我的模板构造函数来解决此问题:

// After TestTemplateClass(int inState), but it's not important
explicit TestTemplateClass(const OwnType &inValue) {
    std::cout << "Copy constructor" << std::endl;
}

这里看起来都不错,但看起来不是一个干净的解决方案。有更好的替代方案吗?

您的实验表明根本没有错误:第一个版本只是使用了复制构造函数,它不打印任何内容,而第二个版本使用了不同的构造函数,因为您实际上禁用了它

(看起来您使用的任何编译器和选项都不会执行RVO)

(N)RVO永远不会在构造函数和析构函数调用的数量之间引入差异。它的目的是使这基本上是不可能的

问题在于你的代码。根据该语言的规则,构造函数模板永远不会用于生成副本构造函数。复制构造函数永远不是模板,句点


因此,类模板实际上并不声明副本构造函数,因此编译器生成默认构造函数(当然不会打印任何内容)。如果在复制构造函数中需要任何特殊处理,则必须始终手动声明。模板永远不会用于实例化模板。

您使用的编译器是什么?您是在调试模式下编译还是禁用了构造函数省略?我只是在发布模式下运行它,没有复制构造函数模板这样的东西,因为标准是这么说的。在第一个示例中,将调用隐式定义的复制构造函数来创建中间副本。你使用的是哪种编译器在删除副本方面如此糟糕?或者您是使用禁用省略的标志进行编译的?我使用的是g++4.6.2。是的,即-未通过模板指定复制构造函数。。。不,我没有。我没有用旗子。是的,你说得对!。。我知道为什么。非常感谢!在复制构造函数之前,我删除了一个“显式”关键字,并得到了正确的输出:默认构造函数复制构造函数析构函数复制构造函数析构函数完成析构函数和关于原始问题。。。智能指针是依赖于三个模板参数(例如ref)类型和策略的模板类,用于拥有内存和访问内存。为了使代码不那么复杂,我尝试创建一些类似于模板别名的东西:带有固定的Owning和Access模板参数值的strong\u ref和weak\u ref。我的g++(4.6.2)版本不支持模板别名。因此,我尝试使用继承(strong_ref:public ref)模拟模板别名,但在“parent”指针中丢失了一些构造函数。@user3621739如果某个答案解决了您的问题,您可以通过单击绿色勾号将其标记为已接受(每个问题最多一个接受答案)。这标志着问题已经解决,并且给了你和回答者一些声誉。是的。哦,谢谢你的解释。。我并没有足够的声誉来提高声誉,但我会把这个问题作为回答。
// 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