我将代码简化为问题的根源:
//==============================================================================
// PRE-DEFINITIONS
#define GIVE_ME_ODD_BEHAVIOUR true
//==============================================================================
// INCLUDES
#include <iostream>
//==============================================================================
// TYPES
//------------------------------------------------------------------------------
template<typename T> struct X {
T data;
X() : data(0)
{ std::cout << "X construction @ " << this << std::endl; }
template<typename TT>
X(const X<TT> & other) : data(other.data)
{ std::cout << "X construction @ " << this << " from " << &other << std::endl; }
~X()
{ std::cout << "X destruction @ " << this << std::endl; }
template<typename TT>
void Copy(const X<TT> & other)
{ std::cout << "X copy @ " << this << " from " << &other << std::endl; }
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<typename T>
X<double> XConversion(const X<T> & other)
{
#if GIVE_ME_ODD_BEHAVIOUR
return X<double>(other);
#else
X<double> d;
d.Copy(other);
return d;
#endif
}
//==============================================================================
// MAIN
int main()
{
X<double> d;
X<int> i;
std::cout << std::endl;
d = XConversion(i);
std::cout << std::endl;
d = XConversion(d); // !!!
std::cout << std::endl;
return 0;
}
,用
GIVE_ME_ODD_BEHAVIOUR true
给出输出:
X construction @ 0x23aa70
X construction @ 0x23aa60
X construction @ 0x23aa80 from 0x23aa60
X destruction @ 0x23aa80
X destruction @ 0x23aa90 // never created !!!
X destruction @ 0x23aa60
X destruction @ 0x23aa70
似乎与THIS问题相似,但我做已定义了ctor。我在这里看到了复制省略优化点,但是:
其他信息:
我尝试了gcc 4.8.1和C ++ Builder XE3,优化关闭,调试编译,两者都有相同的结果。
我试图删除像
这样的模板struct X {
double data
...
X(const X &)
...
};
但结果相同。
解决此问题的一种方法是,例如,将cctor设为私有,并仅公开Copy方法。但这会阻止我(任何人)甚至从函数中返回对象......
背景:
我有一组模板类,它们是相互朋友和可转换的。这些类共享相同的数据,但通过部分特化以不同的方式操作它们。实例可以根据需要执行数据的软拷贝或原始拷贝。如果他们进行软拷贝,则增加ref计数器。通过额外删除实际上从未创建的实例,ref计数器在没有先前增量的情况下减少。
答案 0 :(得分:4)
似乎编译器为你的案例生成了一个拷贝构造函数,也许它不喜欢带有模板的那个(如果我没记错的话,拷贝构造函数不是(或可能不是)基于模板......虽然这里可能是错的) ......见:Copy constructor of template class
添加以下代码:
X(const X & other) : data(other.data)
{ std::cout << "X Copy construction @ " << this << " from " << &other << " as " << typeid(X).name() << std::endl; }
template<typename TT>
X(const X<TT> & other) : data(other.data)
{ std::cout << "X construction @ " << this << " from " << &other << " as " << typeid(TT).name() << std::endl; }
给出以下输出:
X construction @ 0x7fff3496c040
X construction @ 0x7fff3496c038
X construction @ 0x7fff3496c020 from 0x7fff3496c038 as i
X destruction @ 0x7fff3496c020
X Copy construction @ 0x7fff3496c018 from 0x7fff3496c040 as 1XIdE
X destruction @ 0x7fff3496c018
X destruction @ 0x7fff3496c038
X destruction @ 0x7fff3496c040
所以有你遗失的物品。 (用clang和g ++测试,相同的行为)