当条件运算符c?x:y
的两个返回参数不是同一类型时,将在应用强制转换之前进行复制。在保持简单易用性的同时可以防止这种情况吗?
我有这个(针对问题进行了整理):
struct Fixed {
char data[10];
Fixed(char *s) { strcpy(data, s); }
operator char*() { return this->data; }
};
但是它与条件运算符和nullptr的行为确实很差:
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_t
。 f
将强制转换为char*
,但前提是先将其复制。看来这是极其恶劣的行为,但这正是规范所说的。我当前的解决方法是只使 Actor 和ctor
explicit
,但这种可用性的破坏有点。还有其他解决方案吗?这是一些示例代码(忽略质量,因为我正在大量使用它来查看gcc和LLVM如何以不同的方式处理它):
#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;
}
最佳答案
您的问题是三元数的操作数的类型为std::nullptr_t
和struct Fixed
。推理规则将查找从一种操作数类型到另一种以及普通基类的转换。没有机会推断char*
。
您可以通过提供operator std::nullptr_t() = delete
来自动发现错误。
关于c++ - 条件运算符从其参数的拷贝返回值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56225783/