C ++根据条件通过复制或使用引用进行初始化
C++ Initialization by making a copy or using reference depending on the condition
І 有一个名为 do_copy
的 bool
变量。
如果do_copy == true
,我想用副本工作,比如
some_type model = input_model
如果do_copy == false
,我想使用参考,比如
some_type& model = input_model
满足我要求的代码:
some_type copy_model;
if (do_copy)
copy_model = input_model;
some_type& model = do_copy ? copy_model : input_model;
看起来不太好,我调用了默认构造函数,do_copy == false
不需要。
有没有办法让它更优雅?
避免不必要的构造函数的一种方法是仅在需要时动态分配 copy_model
:
std::unique_ptr<some_type> copy_model;
if (do_copy)
copy_model = std::make_unique<some_type>(input_model);
some_type& model = copy_model ? *copy_model : input_model;
虽然我不确定这样更优雅。
将使用 model
的逻辑移动到一个单独的函数中:
void doSomething(some_type& model)
{
//...
}
...
if (do_copy)
{
some_type copy_model = input_model;
doSomething(copy_model);
}
else
doSomething(input_model);
或者,在 C++11 及更高版本中:
template<typename T>
void doSomething(T&& model) // T will be lvalue-ref or rvalue-ref depending on input
{
//...
}
...
if (do_copy)
doSomething(some_type{input_model});
else
doSomething(input_model);
您可以将副本作为三元表达式的一部分:
some_type copy_model;
some_type& model =
do_copy
? (copy_model = input_model, copy_model)
: (input_model);
这仍然需要默认构造 copy_model
即使 do_copy
为 false。如果你的默认构造函数真的很昂贵,你可以使用一个可选的:
std::optional<some_type> copy_model;
some_type& model =
do_copy
? (copy_model = input_model, *copy_model)
: (input_model);
请注意,这并不是完全免费的:与 some_type
相比,std::optional<some_type>
的析构函数有一个额外的分支。
如果您发现自己经常需要这样做,为什么不将此模式包装在 class:
template<class T>
struct copy_or_reference
{
std::optional<T> maybeCopy;
T& ref;
copy_or_reference(copy_tag, T& x)
: ref(x)
{};
copy_or_reference(reference_tag, const T& x)
: maybeCopy(x), ref(*maybeCopy)
{};
operator T& () const { return ref; };
operator T& () { return ref; };
};
template<class T>
auto make_copy_or_reference(bool copy, T& x)
{
return copy ? copy_or_reference<T>(copy_tag{}, x) : copy_or_reference<T>(reference_tag{}, x);
}
void do_something(some_type&);
void do_something_else()
{
...
copy_or_reference<some_type> model = make_copy_or_reference(do_copy, input_model);
do_something(model);
}
І 有一个名为 do_copy
的 bool
变量。
如果do_copy == true
,我想用副本工作,比如
some_type model = input_model
如果do_copy == false
,我想使用参考,比如
some_type& model = input_model
满足我要求的代码:
some_type copy_model;
if (do_copy)
copy_model = input_model;
some_type& model = do_copy ? copy_model : input_model;
看起来不太好,我调用了默认构造函数,do_copy == false
不需要。
有没有办法让它更优雅?
避免不必要的构造函数的一种方法是仅在需要时动态分配 copy_model
:
std::unique_ptr<some_type> copy_model;
if (do_copy)
copy_model = std::make_unique<some_type>(input_model);
some_type& model = copy_model ? *copy_model : input_model;
虽然我不确定这样更优雅。
将使用 model
的逻辑移动到一个单独的函数中:
void doSomething(some_type& model)
{
//...
}
...
if (do_copy)
{
some_type copy_model = input_model;
doSomething(copy_model);
}
else
doSomething(input_model);
或者,在 C++11 及更高版本中:
template<typename T>
void doSomething(T&& model) // T will be lvalue-ref or rvalue-ref depending on input
{
//...
}
...
if (do_copy)
doSomething(some_type{input_model});
else
doSomething(input_model);
您可以将副本作为三元表达式的一部分:
some_type copy_model;
some_type& model =
do_copy
? (copy_model = input_model, copy_model)
: (input_model);
这仍然需要默认构造 copy_model
即使 do_copy
为 false。如果你的默认构造函数真的很昂贵,你可以使用一个可选的:
std::optional<some_type> copy_model;
some_type& model =
do_copy
? (copy_model = input_model, *copy_model)
: (input_model);
请注意,这并不是完全免费的:与 some_type
相比,std::optional<some_type>
的析构函数有一个额外的分支。
如果您发现自己经常需要这样做,为什么不将此模式包装在 class:
template<class T>
struct copy_or_reference
{
std::optional<T> maybeCopy;
T& ref;
copy_or_reference(copy_tag, T& x)
: ref(x)
{};
copy_or_reference(reference_tag, const T& x)
: maybeCopy(x), ref(*maybeCopy)
{};
operator T& () const { return ref; };
operator T& () { return ref; };
};
template<class T>
auto make_copy_or_reference(bool copy, T& x)
{
return copy ? copy_or_reference<T>(copy_tag{}, x) : copy_or_reference<T>(reference_tag{}, x);
}
void do_something(some_type&);
void do_something_else()
{
...
copy_or_reference<some_type> model = make_copy_or_reference(do_copy, input_model);
do_something(model);
}