我的问题(这将按照在此之后,对不起,约长的介绍,问题是向下在那里 大胆)是最初的灵感来自项目23草Sutters 特殊C++ 我们在哪里找到的东西,像这样:
<snip>


...
int main()
{
  GenericTableAlgorithm a( "Customer", MyWorker() );
  a.Process();
}


class GenericTableAlgorithm
{
public:
  GenericTableAlgorithm( const string& table,
                         GTAClient&    worker );
  bool Process(); 
private:
  struct GenericTableAlgorithmImpl* pimpl_; //implementation
};
class GTAClient
{
   ///...
   virtual bool ProcessRow( const PrimaryKey& ) =0;
   //...
};
class MyWorker : public GTAClient 
{
  // ... override Filter() and ProcessRow() to
  //     implement a specific operation ...
};


</snip>

现在,我有以下的问题,代码(不,我没有办法无疑问先生萨特的实力作为一个C++专家):

    1. 例如,将不会的工作,因为GTAClient&工作人员是一个 非常量 参照其可以不采取临时性的,但是,它可能已经写入预的标准或一个错误,不管是什么,这不是我点。
    2. 什么使我不知道为什么他要做的工作人员参考,即使问题1。被忽略。
      很明显意图是有 MyWorker 用于NVI的 GenericTableAlgorithm 访问 GTAClient (多形态)的接口;这个规则出,执行拥有一个(价值)成员的类型 GTAClient, ,因为那将导致切片等。值语义不好多态性。
      它不能具有类型的数据成员 MyWorker 无论是因为这类是未知 GenericTableAlgorithm.
      所以我得出结论,它必须已经意味着要使用通过的指针或基准,保留原来的目的和多态性质。
    3. 由于指针为临时的对象(MyWorker())是很少的一个很好的想法,我认为提交人的计划使用寿命延长时间的临时开(const)参考和储存这样的一个参考的对象 pimpl_ 点和使用它从那里。(注:也没有克隆件的功能在GTAClient,这可能有这样的工作;让我们不要假设有一个RTTI-所属类别基于工厂潜伏在背景中。)
      和这里的(终于来了!) 我的问题组:(如何)可以通过一个临时的一类参考件 与延长生命的时间 做合法?


    该标准在§12.2.5(C++0x版本,但它是相同在C++,不知道有关章节的编号)做出以下例外从寿命延长:"-一个临时的必要参考 会员 在一个构造的构造函数-初始化(12.6.2)仍然存在,直到该构造中退出。"

    因此对象不能使用电话的客户代码 a.过程(); 因为引用的临时从 MyWorker() 已经死了!

    现在考虑的一个例子我自己的手工艺,证明了该问题(测试GCC4.2):

    #include <iostream>
    using std::cout; 
    using std::endl;
    
    struct oogie {
     ~oogie()
     {
      cout << "~oogie():" << this << ":" << m_i << endl;
     }
     oogie(int i_)
      : m_i(i_)
     {
      cout << "oogie():" << this << ":" << m_i << endl;
     }
    
     void call() const
     {
      cout << "call(): " << this << ":" << m_i << endl;
     }
     int m_i;
    };
    
    oogie func(int i_=100)
    {
     return oogie(i_);
    }
    
    struct kangoo 
    {
     kangoo(const oogie& o_)
     : m_o(o_)
     {
     }
    
     const oogie& m_o;
    };
    
    int main(int c_, char ** v_)
    {
    
     //works as intended
     const oogie& ref = func(400);
     //kablewy machine
     kangoo s(func(1000));
    
     cout << ref.m_i << endl;
    
     //kangoo's referenced oogie is already gone
     cout << s.m_o.m_i << endl;
    
     //OK, ref still alive
     ref.call();
     //call on invalid object
     s.m_o.call();
    
     return 0;
    }
    

    其产生的输出

    oogie():0x7fff5fbff780:400
    oogie():0x7fff5fbff770:1000
    ~oogie():0x7fff5fbff770:1000
    400
    1000
    call(): 0x7fff5fbff780:400
    call(): 0x7fff5fbff770:1000
    ~oogie():0x7fff5fbff780:400
    

    你可以看到,在情况下 const oogie&ref 该立即开到参考临时返回值func()具有长寿命,上述参考(直到结束的主要),使它的确定。
    但是:1000oogie对象是已经被摧毁的权利之后,甘果-s构建。代码 工作, 但我们正在处理一个不死的对象在这里...

    所以造成问题再次:
    首先, 我失去了一些东西在这里和代码是正确的/合法的吗?.
    其次, 为什么海湾合作委员会给我没有警告的此,即使墙指定? 应该吗?可以吗?

    感谢您的时间,
    马丁

  • 有帮助吗?

    解决方案

    我认为这是一个棘手的部分,是不是太清楚。有一个类似的问题只是几天前。

    通过默认临时被破坏的顺序相反的施工时充分表达他们的创造完成。到这里的一切都是好的和解,但随后出现的例外情况(12.2[类。临时]/4,5),事情变得混乱。

    而不是处理与的确切措词和定义的标准,我会处理这个问题从工程/编译器的观点。临时创建叠,当一个功能完成堆的框架释放(堆的指针移动回到原来的位置之前的呼叫功能的开始)。

    这意味着一个临时永远不能生存的功能,其中它的创建。更确切地说,它无法生存的范围在它的定义是,即使实际上可以生存的 完整的表达 在其它的创建。

    没有任何例外情况的标准超出这一限制,在所有情况下的使用寿命的临时延长一点,是保证不得超过呼叫功能在临时的创建。

    其他提示

    原来宗师的周篇文章是: 大师的周#15.

    部分答案可能来自药草自己, "一个候选人最重要的常量" -在"常量"的一部分分配一个临时的一个参考的确是重要的。

    因此,它将显示如果这是一个错误的原始文章。

    我一向认为,传递地址参数(无论是通过基准或指针)需要了解有关生的事情过去了。期。结束讨论。这似乎只是一个属性的联合国-垃圾收集/不准管理环境。

    这是一个好处的GC。

    C++有时一生的问题都解决了通过:

    X::克隆人

    或者通过明确的文件的界面,例如:

    "这是最多的初始器的Y确保实例X通过在参数x仍然存在的整个生命周期Y"

    或者通过

    明确复制的x胆量的接收器。

    这只是c++。C++添加一个保证在常量引用的是尼斯(并真正有必要的),但是这样。

    因此,我考虑的代码显示在的问题是错误和我的意见,它应该:

    int main()
    {
      MyWorker w;
      GenericTableAlgorithm a( "Customer", w);
      a.Process();
    }
    

    我不认为你可以这样做与目前的C++。你需要的 移动语义 这将引入C++x0。

    许可以下: CC-BY-SA归因
    不隶属于 StackOverflow
    scroll top