Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用相同的参数名和成员名是否有效 是这个有效的C++,假设我想把参数变量复制到成员变量: struct Struct { Struct(const T& value) : value(value) {} T value; };_C++_Variables_Constructor_Language Lawyer_Argument Passing - Fatal编程技术网

使用相同的参数名和成员名是否有效 是这个有效的C++,假设我想把参数变量复制到成员变量: struct Struct { Struct(const T& value) : value(value) {} T value; };

使用相同的参数名和成员名是否有效 是这个有效的C++,假设我想把参数变量复制到成员变量: struct Struct { Struct(const T& value) : value(value) {} T value; };,c++,variables,constructor,language-lawyer,argument-passing,C++,Variables,Constructor,Language Lawyer,Argument Passing,(更新:它在VisualStudio中工作,但仍然可能依赖于编译器) (预期问题:为什么需要这个?回答:宏制作目的)毫无疑问,它是完全有效的标准一致代码 Struct(const T& value) : value(value) {} ^^^^^ this is argument ^^^^^ this is the member 现在的问题是:这是好的做法吗?在我看来,不是。

(更新:它在VisualStudio中工作,但仍然可能依赖于编译器)
(预期问题:为什么需要这个?回答:宏制作目的)

毫无疑问,它是完全有效的标准一致代码

Struct(const T& value) : value(value) {}
                               ^^^^^ this is argument
                         ^^^^^ this is the member
现在的问题是:这是好的做法吗?在我看来,不是。我更喜欢我的数据成员遵循不同但一致的命名约定,例如数据成员总是以
\uuu
开头。所以我更喜欢这样:

Struct(const T& value) : _value(value) {}
其中,
\u value
是数据成员。您可以遵循任何命名约定,只要确保您的命名一致即可


请注意,在代码变量中,函数、类或任何标识符不应以双下划线(如
\u value
)开头,也不应以单下划线(如
\u value
)后跟大写字母(如
\u value)开头-这些名称是为实现保留的

它是有效的,但是,甚至有必要问这个问题,这就证明了这一点,这可能会引起不安和困惑

一个长期存在的问题是,同一事物有两个截然不同的名称

我喜欢这样做(但有些人讨厌):


对。它确实可以编译。对于编译器,不存在哪个
是哪个的歧义

#include <iostream>

using namespace std;

template <typename T>
struct Struct {
    Struct(const T & value) : value(value) {}
    T value;
};

int main() {

    Struct<int> T(1);
    // your code goes here
    return 0;
}
#包括
使用名称空间std;
模板
结构{
结构(常量T和值):值(值){}
T值;
};
int main(){
结构T(1);
//你的密码在这里
返回0;
}

但在多次声明中,程序员不容易破译。它确实可以工作,因为对于编译器来说,参数屏蔽了成员函数,所以
value(value)
中的第二个
value
是参数,但是由于只有成员和祖先类可以位于
value(value)
的左侧,所以它在这里引用了成员


非常棘手,会使调试和维护变得复杂。

这是有效的,但在某些圈子里是不明智的,包括我的圈子

这是有效的,因为成员变量将根据您的需要由参数正确设置。执行初始值设定项列表后,将隐藏该成员。对
值的任何引用都将访问该参数。这可能是件坏事

这是不明智的,原因有二。首先是可维护性和混乱。参数和成员变量具有相同的名称是不常见的。因此,大多数程序员将不得不停下来思考它的含义。毕竟,你做到了。请记住,代码首先是为程序员编写的,其次是为编译器编写的。易于理解的代码比难以理解的代码要好得多。在代码审查中,我会基于这些理由拒绝该代码

其次,在大多数情况下,成员隐藏可能是一个问题

我建议提出一个合理的命名方案并坚持下去。“Sane”表示参数不能与成员变量同名。例如,在我的命名方案中,成员变量总是在前面加上
m
——参数从不加前缀。因此,在此方案中,您的代码将成为:

struct Struct {
  Struct(const T& value) : mValue(value) {}
  T mValue;
};

使用这个方案,没有人会对这里发生的事情感到困惑,也没有人会问StackOverflow“这合法吗?”

它是有效的。不过有一点警告:更改参数名称和代码是未定义的行为

template <typename T>
struct Struct {
    Struct(const T & argument) : value(value) {}
    T value;
};
模板
结构{
结构(常量T和参数):值(值){}
T值;
};

> > P>这是C++标准允许的,但是考虑到在初始化成员之后,您希望在函数中做更多工作的情况。例如,使用
3
进行一些更有意义的计算:

class Foo
{
public:
    int bar;
    Foo(int bar) : bar(bar) { bar = 3; }
};
函数中的赋值将更改参数
的值,而不是成员
的值。在您的示例中不会发生这种情况,因为您使用
const
声明了参数。因此,如果您确保始终使用
const
声明参数,那么您将受到保护,不受此影响。但是考虑一个更复杂的场景:

class Foo
{
public:
    int bar;
    int baz;
    void AuxiliaryFunction() { bar = 3; }
    Foo(const int &bar) : bar(bar)
    {
        AuxiliaryFunction();
        baz = bar;
    }
};
在本例中,通过构造函数中调用的另一个函数,为成员
bar
提供了一些值。然后赋值
baz=bar
可能用于复制成员
,但实际上它复制参数


>,虽然这是合法的C++,但它应该被明智地使用。

< P>这确实是有效的代码,和其他答案一样,我会警告您,这应该非常小心地使用,因为它可能会混淆,并且可能导致难以维护的代码。 那么,这是为什么?如果我们考虑你的构造函数:

Struct(const T& value) : value(value) {}
                         ^     ^
                         1     2    
1
2
在不同的范围内进行评估。因此,我们需要查看
12.6.2
初始化基和成员一节,并查看一些语法:

ctor-initializer:
    : mem-initializer-list 
mem-initializer-list:
    mem-initializer ...opt
    mem-initializer , mem-initializer-list ...opt
mem-initializer:
    mem-initializer-id ( expression-listopt )
    mem-initializer-id braced-init-list
经过分析,我们发现
1
实际上是一个mem初始值设定项id,
2
是一个表达式listopt,我们可以分别转到第2段和第12段。第2段说:

在mem初始值设定项id中,在构造函数类的作用域中查找初始非限定标识符,如果在该作用域中找不到,则在包含构造函数定义的作用域中查找该标识符。[……]

因此,
1
将首先在课堂上查找,而我们可以从第12段中看到:

mem初始值设定项的表达式列表或大括号初始值列表中的名称在为其指定mem初始值设定项的构造函数的范围内求值

2
将在构造函数的范围内查找。因此
1
将首先查找成员变量并停止查找,而
2
将查找构造函数并查找参数。这也意味着如果你想引用
ctor-initializer:
    : mem-initializer-list 
mem-initializer-list:
    mem-initializer ...opt
    mem-initializer , mem-initializer-list ...opt
mem-initializer:
    mem-initializer-id ( expression-listopt )
    mem-initializer-id braced-init-list