【问题标题】:Compiler destructs an optimized-out object (never created)编译器破坏一个优化的对象(从未创建)
【发布时间】:2014-09-05 15:53:06
【问题描述】:

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

//==============================================================================
// 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 方法。但这会阻止我(任何人)甚至从函数中返回对象......


背景:

我有一组互为好友且可转换的模板类。这些类共享相同的数据,但通过部分专业化以不同的方式操作它们。实例可以根据需要对数据进行软拷贝或原始拷贝。如果他们进行软拷贝,则引用计数器会增加。随着实际从未创建的实例的额外删除,引用计数器在没有事先增加的情况下减少。

【问题讨论】:

  • @AdrianoRepetti 他没有复制构造函数。

标签: c++ constructor destructor compiler-optimization


【解决方案1】:

似乎编译器为您的情况生成了一个复制构造函数,也许它不喜欢带有模板的那个(如果我没记错的话,复制构造函数不是(或可能不是)基于模板的......虽然在这里可能是错误的) ...见: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++ 测试,行为相同)

【讨论】:

  • 只是为了确认:模板化构造函数被视为复制构造函数,因为它不会阻止编译器生成一个。 (另一方面,在选择要调用的构造函数时,编译器考虑模板实例化,即使在您正在复制的上下文中。例如,如果他的非模板复制构造函数采用非常量引用,并且他正在复制一个临时的,将选择模板实例化。)
猜你喜欢
  • 2016-04-22
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多