c ++匿名构造函数做奇怪的事情

c++ anonymous constructor doing weird things

此示例程序展示了如何根据您传入的是局部变量、全局变量还是匿名变量来调用不同的构造函数。这是怎么回事?

std::string globalStr;
class aClass{
public:
  aClass(std::string s){
    std::cout << "1-arg constructor" << std::endl;
  }
  aClass(){
    std::cout << "default constructor" << std::endl;
  }
  void puke(){
    std::cout << "puke" << std::endl;
  }
};

int main(int argc, char ** argv){
  std::string localStr;
  //aClass(localStr); //this line does not compile
  aClass(globalStr);  //prints "default constructor"
  aClass(""); //prints "1-arg constructor"
  aClass(std::string("")); //also prints "1-arg constructor"
  globalStr.puke(); //compiles, even though std::string cant puke.
}

鉴于我可以调用 globalStr.puke(),我猜测通过调用 aClass(globalStr);,它正在创建一个名为 globalStr 且类型为 aClass 的局部变量,即正在使用而不是全局 globalStr。调用 aClass(localStr); 试图做同样的事情,但编译失败,因为 localStr 已经声明为 std::string。是否可以通过使用非常量表达式调用其 1-arg 构造函数来创建 class 的匿名实例?谁决定 type(variableName); 应该是定义名为 variableName 的变量的可接受方式?

aClass(localStr); //this line does not compile

这试图声明一个名为 localStr 的类型 aClass 的变量。语法很糟糕,我同意,但现在 [改变标准] 已经太晚了。

aClass(globalStr);  //prints "default constructor"

这声明了一个名为 globalStr。这个 globalStr 变量隐藏了全局变量。

aClass(""); //prints "1-arg constructor"

这将创建类型为 aClass 的临时对象。

aClass(std::string("")); //also prints "1-arg constructor"

这也会创建一个临时文件。

globalStr.puke(); //compiles, even though std::string cant puke.

这使用 main 中的 globalStr,这与所有其他阴影实例一致。

Is it possible to create an anonymous instance of a class by calling its 1-arg constructor with a non-constant expression?

是的,我可以想到四种方法:

aClass{localStr}; // C++11 list-initialization, often called "uniform initialization"
(void)aClass(localStr); // The regular "discard this result" syntax from C.
void(aClass(localStr)); // Another way of writing the second line with C++.
(aClass(localStr)); // The parentheses prevent this from being a valid declaration.

作为旁注,这种语法通常是最令人烦恼的解析的原因。例如,下面声明了一个函数 foo returns aClass,其中一个参数 localStr 类型为 std::string:

aClass foo(std::string(localStr));

事实上,这是导致您的问题的相同规则 - 如果某些内容可以被解析为有效声明,那么它一定是。这就是为什么 aClass(localStr); 是一个声明而不是由一个单独的表达式组成的语句。