C++;变量生存期--需要解决方法返回临时 我有一个C++对象( Boo::格式< />代码>),它有一个()/函数,它返回一个 STD::String

C++;变量生存期--需要解决方法返回临时 我有一个C++对象( Boo::格式< />代码>),它有一个()/函数,它返回一个 STD::String,c++,cstring,stdstring,object-lifetime,boost-format,C++,Cstring,Stdstring,Object Lifetime,Boost Format,因此,当我需要格式化的C字符串时,我需要编写如下内容: (boost::format("%1% %2%") % "1" % "2").str().c_str() 我觉得这相当冗长,我非常需要它。我想创建一个派生类,它有一个操作符char*,工作方式如下(Ch=char或wchar\t): 当然,当函数返回时,str()返回的字符串将被释放,并且不会返回有效的C字符串 有什么解决办法吗 该解决方案需要创建一个字符串,该字符串只要周围函数调用: lib_function((boost::forma

因此,当我需要格式化的C字符串时,我需要编写如下内容:

(boost::format("%1% %2%") % "1" % "2").str().c_str()
我觉得这相当冗长,我非常需要它。我想创建一个派生类,它有一个
操作符char*
,工作方式如下(Ch=char或wchar\t):

当然,当函数返回时,
str()
返回的字符串将被释放,并且不会返回有效的C字符串

有什么解决办法吗

该解决方案需要创建一个字符串,该字符串只要周围函数调用:

lib_function((boost::format("%1% %2%") % "1" % "2").str().c_str()); 
// can be deallocated here

返回堆栈上的std::字符串。这是一个额外的副本,因此如果性能很重要,这是一个坏主意,但它可以消除大多数冗余键入。

在堆栈上返回一个std::string。这是一个额外的副本,因此如果性能很重要,这是一个坏主意,但它可以消除大多数冗余键入。

您可以定义如下所示的结构:

struct my_str
{
  const std::string &tmp;
  my_str(const boost::format &tmp) : tmp( tmp.str() ) {}
  operator const char *() const { return tmp.c_str(); }
};
你可以这样称呼它

lib_function ( my_str(boost::format("%1% %2%") % "1" % "2") );

如果您担心引用会悬空,请阅读本文。

您可以定义如下所示的结构:

struct my_str
{
  const std::string &tmp;
  my_str(const boost::format &tmp) : tmp( tmp.str() ) {}
  operator const char *() const { return tmp.c_str(); }
};
你可以这样称呼它

lib_function ( my_str(boost::format("%1% %2%") % "1" % "2") );

如果您担心引用会悬空,请阅读本文。

最明显的解决方案是定义一个包含
std::string
,并隐式转换为
字符常量*
。 比如:

class ToPlainC
{
    std::string myValue
public:
    ToPlainC( boost::format const& fmt )
        : myValue( fmt.str() )
    {
    }
    operator char const*() const
    {
        return myValue.c_str();
    }
};
可用于:

lib_function( ToPlainC( boost::format( "%1% %2%" ) % "1" % "2" ) );
这种隐式转换通常不是一个好主意,但如果 你很好地记录了这个类,它应该只用于 这种特殊的情况,我认为是可以接受的

编辑:

我突然想到,鼓励只使用这个类作为 在这个特定场景中,您可以将其命名为临时 使用通常用于函数的命名约定,以及 不是那些你用来上课的;然后,用户将拥有 给人的印象是他正在使用一个函数,而且它会很突出
如果他不这样使用它,那就好像大拇指疼痛一样。

最明显的解决方案是定义一个包含
std::string
,并隐式转换为
字符常量*
。 比如:

class ToPlainC
{
    std::string myValue
public:
    ToPlainC( boost::format const& fmt )
        : myValue( fmt.str() )
    {
    }
    operator char const*() const
    {
        return myValue.c_str();
    }
};
可用于:

lib_function( ToPlainC( boost::format( "%1% %2%" ) % "1" % "2" ) );
这种隐式转换通常不是一个好主意,但如果 你很好地记录了这个类,它应该只用于 这种特殊的情况,我认为是可以接受的

编辑:

我突然想到,鼓励只使用这个类作为 在这个特定场景中,您可以将其命名为临时 使用通常用于函数的命名约定,以及 不是那些你用来上课的;然后,用户将拥有 给人的印象是他正在使用一个函数,而且它会很突出

如果他不这样做,那他就像一个受伤的拇指。

不要使用
c_str
或字符指针?@JoachimPileborg当涉及到第三方API时,说起来容易做起来难…不要使用
c_str
或字符指针?@JoachimPileborg当涉及到第三方API时,说起来容易做起来难…这是行不通的,出于类似的原因,我的答案没有给出-绑定到构造函数参数的临时变量在构造函数结束时结束其生命周期。不过,如果您按值而不是按引用存储
tmp
,它将起作用。RVO很可能会避免任何复制。我检查了一次构造和销毁顺序。你的意思是说订单行为是未定义的还是未指定的?从它的规格中添加有助于更好地理解。12.2临时对象,第3条:“临时对象被销毁,作为评估完整表达式(1.9)的最后一步,该表达式(词汇上)包含临时对象创建的点。”1.9程序执行,第12条:“完整表达式是不是另一个表达式的子表达式的表达式。
my_str
与其用法不匹配-它采用
const std::string&
,而不是
const boost::format&
;这就是问题所在。是的,现在它起作用了。但是它只保存
.c_str()
后缀,而不是OP所需的完整
.str().c_str()
。这不会起作用,因为我的答案与此类似-绑定到构造函数参数的临时变量在构造函数结束时结束其生命周期。不过,如果您按值而不是按引用存储
tmp
,它将起作用。RVO很可能会避免任何复制。我检查了一次构造和销毁顺序。你的意思是说订单行为是未定义的还是未指定的?从它的规格中添加有助于更好地理解。12.2临时对象,第3条:“临时对象被销毁,作为评估完整表达式(1.9)的最后一步,该表达式(词汇上)包含临时对象创建的点。”1.9程序执行,第12条:“完整表达式是不是另一个表达式的子表达式的表达式。
my_str
与其用法不匹配-它采用
const std::string&
,而不是
const boost::format&
;这就是问题所在。是的,现在它起作用了。但它只保存
.c_str()
后缀,而不是完整的
.str()。如果我们将myValue设为字符串的常量引用,该怎么办。我相信这种行为仍然是有定义的@詹姆斯,你能分享一下你的观点吗?+1这让我想到了如何在没有任何额外文字的情况下完成这项工作。我的“cformat”类继承自boost::function,定义了
operator%
operator Ch const*
,因此现在我可以编写
lib_函数(cformat(“%1%%2%”)1%%“2”)
@MohitJain生成
myValue
引用会导致未定义的行为:初始化初始值设定项列表中的常量引用是一种特殊情况,它仅扩展