有条件的操作员从其参数的副本中返回值

Conditional operator returns value from a copy of its argument

本文关键字:副本 返回值 参数 操作员 有条件      更新时间:2023-10-16

当两个返回条件运算符c?x:y的返回参数不具有相同类型时,在应用铸件之前制作了副本。可以在保持简单的useabiltiy时被阻止吗?

我有这个(修剪问题(:

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_tf将通过演员 char*进行,但仅在首先复制之后。这似乎是极差的行为,但这是规格所说的。

我目前的解决方案是使演员和CTOR explicit,但有点可用性的废墟。还有其他解决方案吗?

这里有一些示例代码(忽略质量,因为我在大量使用此操作时,以查看GCC和LLVM的处理方式不同(:

#include <cstdio>
#include <iostream>
#include <array>
#include <cstring>
using namespace std;
struct A : public array<char,4> {
  A() { cerr<<"defn"; }
  A(const A &o) { cerr<<"copyn"; (*this)=o;}
  A(const char *s) { cerr<<"ctorn";assign(s); } // explicit fixes
  void assign(const char*s) {cerr<<"assignn";memset(this->begin(), 0, 4); strncpy(this->begin(), s, 4); }
  operator char*() { cerr<<"castn";return this->begin(); }
  //operator void*() { cerr<<"voidn";return this->begin(); }
  //operator std::nullptr_t() { cerr<<"voidn";return (std::nullptr_t)this->begin(); }
};
volatile A *faraway = new A();
char* plain(A &v) { cerr<<"in pln";
  return faraway == nullptr ? nullptr : v;
}
char* cast1(A &v) { cerr<<"in c1n";
  return faraway == nullptr ? (char*)nullptr : v;
}
char* cast2(A &v) { cerr<<"in c2n";
  return faraway == nullptr ? nullptr : (char*)v;
}
int main() {
  A *a = new A; a->assign("asd");
  char *x = a->data();
  cerr << "nplainn";
  char *yp = plain(*a);
  cerr << "nc1n";
  char *y1 = cast1(*a);
  cerr << "nc2n";
  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_tstruct Fixed。推论规则将寻找从一种操作数类型到另一种操作数类型以及共同基础类别的转换。没有机会推断char*

您可以通过提供operator std::nullptr_t() = delete;

自动捕获错误