编译器破坏优化的对象(从未创建)

时间:2014-07-15 12:38:34

标签: c++ constructor destructor compiler-optimization

我将代码简化为问题的根源:

//==============================================================================
// 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。我在这里看到了复制省略优化点,但是:

  • 为什么copiler会破坏它优化的对象,从而永远不会创建?
  • 我怎样才能确保它不会发生?

其他信息:

我尝试了gcc 4.8.1和C ++ Builder XE3,优化关闭,调试编译,两者都有相同的结果。

我试图删除像

这样的模板
struct X {

  double data
  ...
  X(const X &)
  ...

};

但结果相同。

解决此问题的一种方法是,例如,将cctor设为私有,并仅公开Copy方法。但这会阻止我(任何人)甚至从函数中返回对象......


背景:

我有一组模板类,它们是相互朋友和可转换的。这些类共享相同的数据,但通过部分特化以不同的方式操作它们。实例可以根据需要执行数据的软拷贝或原始拷贝。如果他们进行软拷贝,则增加ref计数器。通过额外删除实际上从未创建的实例,ref计数器在没有先前增量的情况下减少。

1 个答案:

答案 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 ++测试,相同的行为)