我有一个指向类MyObject
的引用,但具体的对象取决于一个条件。我想做这样的事情:
MyObject& ref;
if([condition])
ref = MyObject([something]);
else
ref = MyObject([something else]);
我现在无法做到这一点,因为编译器不允许我声明但不初始化引用。在这种情况下,我该怎么做才能实现我的目标呢?
你需要初始化它。但是如果你想有条件地初始化它,你可以这样做:
MyObject& ref = (condition) ? MyObject([something]) : MyObject([something else]);
据我所知,这不能使用引用完成。你需要使用指针:
MyClass *ptr;
if (condition)
ptr = &object;
else
ptr = &other_object;
指针类似于引用,只是别忘了使用->
来访问成员。
MyClass &ref = *ptr
这样的语句来声明一个引用。请注意,此语句仅限于将指针转换为引用,并不会改变指针本身的类型或值。 - poizan42new
分配内存时才会如此。ptr
指向在堆栈上分配的对象。 - David Gptr
变成值类型并分配给值。如果它不能默认初始化,那么我会建议使用std::unique_ptr
,并在每个条件中使用std::make_unique<MyClass>(...)
进行分配。 - David G我喜欢做的是立即执行的lambda表达式。
假设我们想要一个 const std::string& 类型的变量,从映射中获取一个键对应的值 - 如果映射中不包含给定的键,则会抛出异常。
int main()
{
std::map<std::string, std::string> myMap = {{"key", "value"}};
const std::string& strRef = [&]()->const std::string& {
try {
return myMap.at("key"); // map::at might throw out_of_range
}
catch (...) {
// handle it somehow and/or rethrow.
}
}(); // <- here we immediately call just created lambda.
}
自C++17起,您还可以使用std::invoke()使其更易读。
int main()
{
std::map<std::string, std::string> myMap = {{"key", "value"}};
const std::string& strRef = std::invoke([&]()->const std::string& {
try {
return myMap.at("key"); // map::at might throw out_of_range
}
catch (...) {
// handle it somehow and/or rethrow.
}
});
}
MyObject obj;
if([condition])
obj = MyObject([something])
else
obj = MyObject([something else]);
const MyObject& ref = createObject([condition]);
或者
const MyObject& ref = [condition] ? doSomething() : doSomethingElse();
MyObject obj = createObject([condition]);
这个方法可能和你之前尝试的一样有效,多亏了返回值优化。
class test{ test(param o ):ref(o){}myobj& ref;}
- RaGa__M简短回答:你不需要这样做。
稍微详细一些的回答:可以尝试像这样做:
MyObject& getObject()
{
if([condition])
return [something]
else
return [something else];
}
MyObject& ref = getObject();
当然,通常适用于参考文献的免责声明也适用于此。
getObject()
为什么会返回一个引用?它所指的是什么? - Jonathan WakelyMyClass *ptr;
if (condition)
ptr = &object;
else
ptr = &other_object;
MyClass &ref = *ptr;
MyClass &ref = *ptr;
,这是避免后续进一步解引用的关键行,更多注释请参见:https://dev59.com/E2ox5IYBdhLWcg3wcj94#62793754 - Ciro Santilli OurBigBook.com可以使用静态的虚拟对象或者带有引用包装器的std::optional作为占位符。
static X placeHolder_;
std::reference_wrapper<X> ref = placeHolder_;
std::optional<std::reference_wrapper<X>> ref ;
Ivar& ref; // invalid, need init
if([condition]){
ref = data["info"];
if (ref.is_dict()) {
...
}
}
string x = ref["aa"];
在条件语句中使用临时变量
Ivar& ref = dict(); // Ivar and dict are faked; Ivar is interface variable
if([condition]){
Ivar& ref_tmp = data["info"];
if (ref_tmp.is_dict()) { // if the type of temp variable is correct
ref = ref_tmp // assign ref_tmp to ref
...
}
}
string x = ref["aa"];
std::shared_ptr<ObjType> pObj;
if(condition)
pObj = std::make_shared<ObjType>(args_to_constructor_1);
else
pObj = std::make_shared<ObjType>(args_to_constructor_2);
它是干净的,并且允许使用对象定义与(可能不同的)构造,这是您不能直接使用指针进行的临时对象的编译器将抱怨的事情。
MyObject& ref = MyObject([something]);
, because you cannot bind a temporary to a non-const lvalue reference."意思是:这是从一份临时代码中提取出来的注释。即使没有条件限制,如下初始化方式也行不通:MyObject& ref = MyObject([something]);
,因为你不能将临时对象绑定到非 const 左值引用上。 - GManNickG