C++ 条件运算符从其参数的副本返回值
如果条件运算符C++ 条件运算符从其参数的副本返回值,c++,conditional-operator,temporary-objects,C++,Conditional Operator,Temporary Objects,如果条件运算符c?x:y的两个返回参数不是同一类型,则在应用强制转换之前会进行复制。在保持简单可用性的同时,是否可以防止这种情况 我有以下内容(问题减少): 但它在条件运算符和null ptr中的行为非常糟糕: Fixed f =...; // just here to show the type of f, don't read too much into this ... bool condition = ...; char *s = condition ? nullptr : f; 制作
c?x:y
的两个返回参数不是同一类型,则在应用强制转换之前会进行复制。在保持简单可用性的同时,是否可以防止这种情况
我有以下内容(问题减少):
但它在条件运算符和null ptr中的行为非常糟糕:
Fixed f =...; // just here to show the type of f, don't read too much into this
...
bool condition = ...;
char *s = condition ? nullptr : f;
制作了f的副本,s现在指向堆栈上的一个值,该值很快就会消失。这一切都是因为nullptr
的类型是std::nullptr\u t
f
将通过转换到char*
,但仅在首先复制它之后。这似乎是非常糟糕的行为,但这是规范所说的
我目前的解决方案是使强制转换和ctor显式化
,但这会稍微破坏可用性。还有其他解决办法吗
下面是一些示例代码(忽略质量,因为我正在大量使用它,以了解gcc和LLVM如何以不同方式处理此问题):
#包括
#包括
#包括
#包括
使用名称空间std;
结构A:公共数组{
A(){cerr您的问题是三元操作数的类型为std::nullptr\u t
和struct Fixed
。推理规则查找从一种操作数类型到另一种操作数类型的转换以及公共基类。没有机会推断char*
您可以通过提供操作符std::nullptr_t()=delete
;自动捕捉错误cond?nullptr:(char*)f
工作正常。cond?(char*)nullptr:f
在LLVM中工作正常,但GCC拒绝编译(并且我将修复(char*)
@JohnKugelman是的,基本上。我只是在那里显示f
的类型。结构是从散列中检索的,因此我试图在散列中返回结构的char*
,而不是返回堆栈上结构副本的char*
。使用somefunc(a&v)
那么&v
就不能是null ptr。请给出一个更好的例子或一个更好的设计。@Ripi2:令人惊讶的是,这不是真的。你可以做somefunc(*(a*)nullptr)
,只要不做从左值到右值的转换,这是合法的。@BenVoigt让我惊讶,是的。无论如何,我认为OP想要使用char*x=somefunc(someinstance)
其中someinstance
不是指针,而是类实例。但它似乎推断出char*
。它甚至调用了正确的操作符char*
方法。这只是一种奇怪的需要,需要先创建一个临时对象(以及GCC要求修复(char*)的奇怪行为)
ctor,但不实际使用它)。@JasonN:它不推断char*
,三元计算结果是一个struct-Fixed
临时对象。然后运算符char*()
在char*
变量初始化期间被调用。您可以通过在变量之间引入一个auto
类型的变量来证明这一点,比如auto t=condition?nullptr:f;我是否认为三元,必须从两个分支返回相同的类型,在这种情况下,它需要在ternar之前进行推断y(即,我不能返回A
,除非if可以从nullptr
转换为A
)…我刚刚用auto
进行了测试,并强制一个编译器错误来查看类型。三元组返回一个a
,这也意味着有一个从nullptr
到a
的隐式转换可能?我不明白这是怎么可能的?如果比较是真的,那就更糟糕了,nullptr
被转换成一个A,它在没有编译器警告的情况下会出现故障。为什么它甚至可以将nullptr__t转换成任何非指针类型呢?再多玩一点,我就可以让编译器承认它可以从nullptr___t
转换成A
和/反之亦然/。很难看,但我想它不会比其他C更糟糕++丑陋。Shrugd你认为这是一个需要a(char*)
来编译的GCC错误,不像LLVM,而且从不使用它吗?我应该报告它吗?
Fixed f =...; // just here to show the type of f, don't read too much into this
...
bool condition = ...;
char *s = condition ? nullptr : f;
#include <cstdio>
#include <iostream>
#include <array>
#include <cstring>
using namespace std;
struct A : public array<char,4> {
A() { cerr<<"def\n"; }
A(const A &o) { cerr<<"copy\n"; (*this)=o;}
A(const char *s) { cerr<<"ctor\n";assign(s); } // explicit fixes
void assign(const char*s) {cerr<<"assign\n";memset(this->begin(), 0, 4); strncpy(this->begin(), s, 4); }
operator char*() { cerr<<"cast\n";return this->begin(); }
//operator void*() { cerr<<"void\n";return this->begin(); }
//operator std::nullptr_t() { cerr<<"void\n";return (std::nullptr_t)this->begin(); }
};
volatile A *faraway = new A();
char* plain(A &v) { cerr<<"in pl\n";
return faraway == nullptr ? nullptr : v;
}
char* cast1(A &v) { cerr<<"in c1\n";
return faraway == nullptr ? (char*)nullptr : v;
}
char* cast2(A &v) { cerr<<"in c2\n";
return faraway == nullptr ? nullptr : (char*)v;
}
int main() {
A *a = new A; a->assign("asd");
char *x = a->data();
cerr << "\nplain\n";
char *yp = plain(*a);
cerr << "\nc1\n";
char *y1 = cast1(*a);
cerr << "\nc2\n";
char *y2 = cast2(*a);
cerr << "\n---\n";
cerr << (void*)a << "\n" << (void*)(a->data()) << "\n" << (void*)x << "\n---\n";
cerr << (void*)yp << "\n" << (void*)y1 << "\n" << (void*)y2 << "\n";
return 0;
}