C++ 在构造函数初始化中重用临时构造函数

C++ 在构造函数初始化中重用临时构造函数,c++,constructor,temporary,C++,Constructor,Temporary,在初始化构造函数中类的成员时,如何在多个点上使用相同的临时值 例如: // for arbitrary T1, T2, T3 T2 foo(T1 const&); T3 bar(T1 const&); struct A { T2 const t2; T3 const t3; A() : t2(foo(T1())), t3(bar(T1())) {} }; 这是一个非常简化的示例,但是t2和t3都是根据T1的实例构造的。现在,如果我想让这个对象在两个初始化中完全相同

在初始化构造函数中类的成员时,如何在多个点上使用相同的临时值

例如:

// for arbitrary T1, T2, T3
T2 foo(T1 const&);
T3 bar(T1 const&);

struct A {
  T2 const t2;
  T3 const t3;
  A() : t2(foo(T1())), t3(bar(T1())) {}
};
这是一个非常简化的示例,但是
t2
t3
都是根据
T1
的实例构造的。现在,如果我想让这个对象在两个初始化中完全相同,我有一个问题,因为它没有名字。您知道如何在不使用C++11构造函数调用构造函数功能,也不添加调用
a(T1())
的伪类的情况下解决这个问题吗


*像这样:

  A(T1 const& t1) : t2(foo(t1)), t3(bar(t1)) {}


动机:如果
T1()
实际上类似于
newt()
,其中对象的地址很重要,因此我必须在
t2
t3

中讨论同一个对象,那么在构造函数初始化中重用临时对象的肮脏方式就是添加一个伪参数。我不喜欢这项技术,但我知道这是唯一一个给临时工起名字的技术。我倾向于重新设计我的类来避免这种情况

struct A
{
    A( T1 temporary_ = T1() )
      : t2( foo( temporary_ ) )
      , t3( bar( temporary_ ) )

    T2 const t2;
    T3 const t3;
};

我会通过创建一个工厂方法来解决这个问题

// for arbitrary T1, T2, T3
T2 foo(T1 const&);
T3 bar(T1 const&);

struct A {
    T2 const t2;
    T3 const t3;
    static A createA() { return A(T1()); }

  private:
     A(const T1& t) : t2(foo(t)), t3(bar(t)) {}
};

Const引用可能默认为临时引用,最近(我忘了这是C++03还是C++11的添加):


(为了以防万一,可能会声明构造函数
explicit

我会不惜一切代价避免这种情况,但如果必须,我会添加一个额外的成员:

struct A {
  T1 temp_;
  T2 const t2;
  T3 const t3;
  A() : temp_(), t2(foo(temp_)), t3(bar(temp_)) {}
};

真的需要吗?因为通常创建这样的临时文件几乎不需要任何时间。@MooingDuck:你怎么知道的?也许T1的构造器首先开始抓取互联网络…@bitmask:你不能让T2将它的T1公开给T3/A吗?就像
t2(foo(T1())、t3(bar(t2.getT1())
@MooingDuck:正如我在动机中所说的,它实际上是一个
新的T(x,y,z)
调用,而不是一个自动临时调用(指针仍然是临时的,但实际对象是在堆上分配的)。不,不幸的是,我不能把
A
作为一篇作文。@bitmask:远离问题:我想我们现在至少遇到了两个障碍,它们是问题的重要补充。如果你能在第一轮提问时尝试将更多的内容纳入到问题中(避免人们浪费时间),那么对这么多人来说,这真的会好得多。这通常被称为“告诉我们你已经尝试了什么,以及为什么没有成功”。在某种程度上,我喜欢这个问题,因为它是如此简洁,但这是骗人的。我的$0.02i处于一个复杂而复杂的类层次结构中,有一些非平凡的构造函数。如果有人真的想给我一个
T1()
,我想这不会有什么伤害。@bitmask:这是它的主要问题,它改变了用户看到的界面。如果它没有损害你的设计,那么它只是一个可以接受的副作用。我真的不喜欢公共头中的默认函数参数(版本控制+重新编译+ODR,重写和重载IMHO有太多问题),但考虑到OP添加的所有额外的ifs和buts,它确实开始看起来像一个现实的选项+1@sehe:的确如此。我很想听听另一种技术。大多数情况下,我最终设计了内部类来容纳这两个成员,并提供适当的构造。@K-ballo:我可能会把它与函数模板的默认模板参数混淆起来。哦,好吧。也许有人可以澄清这符合哪一个标准。这确实是一种扭曲,事实上我已经有了这样一个成员,但我需要将临时类传递给我的父类,我必须首先初始化它(我试图使问题尽可能抽象和简化,但似乎我删掉了太多内容;很抱歉!)。然后我将把值存储在父类中,然后通过基类型引用它:
A():base(T1())、t2(foo(base::m_T1))、t3(bar(base::m_T1)){}
。但是,请注意,如果
base::base(…),则您可能会遇到临时if的生存期问题
获取临时对象的地址。@bitmask--哦,我从你的其他评论中看到,你实际上不需要相同的临时对象,只需要相同的值。忽略我关于生存期的评论。@bitmask:
但是我需要将临时对象传递给我的父类。
-嗯,我开始觉得你的代码库有很大的设计问题。当然,一个类层次结构不可能同时遭受所有设计问题的困扰?相反,如果需要所有这些复杂性,那么成本也是合理的?使用工厂模式、存储库模式、构建器模式、复合模式、flyweights、IoC等任何存在的模式。是的,它会付出代价,但这就是生命。@sehe:我知道它看起来像这一点没有人特别引以为傲,但我认为这一点有一个非常合理的设计。对于您的复杂性点:工厂、模板、动态绑定、flyweight,以及某种程度上的IoC,都是为了这个构造函数所涉及的构造而准备的(顺便说一句,这是我遗漏信息的原因之一)。
struct A {
  T1 temp_;
  T2 const t2;
  T3 const t3;
  A() : temp_(), t2(foo(temp_)), t3(bar(temp_)) {}
};