在C++ 11之前,我们只能对整数或枚举类型的静态const成员执行类内初始化.Stroustrup在他的C++ FAQ中讨论了这个问题,给出了以下示例:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
Run Code Online (Sandbox Code Playgroud)
以下推理:
那么为什么存在这些不方便的限制呢?类通常在头文件中声明,并且头文件通常包含在许多翻译单元中.但是,为避免复杂的链接器规则,C++要求每个对象都有唯一的定义.如果C++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏.
但是,C++ 11放宽了这些限制,允许非静态成员的类内初始化(§12.6.2/ 8):
在非委托构造函数中,如果给定的非静态数据成员或基类未由mem-initializer-id指定(包括没有mem-initializer-list的情况,因为构造函数没有ctor-initializer)然后,实体不是抽象类(10.4)的虚基类
- 如果实体是具有大括号或等于初始值的非静态数据成员,则按照8.5中的规定初始化该实体;
- 否则,如果实体是变体成员(9.5),则不执行初始化;
- 否则,实体默认初始化(8.5).
第9.4.2节还允许非const静态成员的类内初始化,如果它们用说明constexpr符标记的话.
那么我们在C++ 03中受到限制的原因究竟发生了什么?我们只是简单地接受"复杂的链接器规则"或者是否有其他改变使得这更容易实现?
在C++ 5.1.1/3 [expr.prim.general]中,它说:
类型和值类别[of
this]在静态成员函数中定义.
这是什么意思?它有什么关系?
注意:
this不应出现在静态成员函数的声明中
我一直在观看Scott Meyers 关于 C++和2012 年之后的Universal References的演讲,到目前为止一切都很有意义.然而,一位观众在大约50分钟后问了一个问题,我也在想.迈尔斯说,他不关心答案,因为它不是惯用的,会愚蠢的想法,但我仍然感兴趣.
提供的代码如下:
// Typical function bodies with overloading:
void doWork(const Widget& param) // copy
{
// ops and exprs using param
}
void doWork(Widget&& param) // move
{
// ops and exprs using std::move(param)
}
// Typical function implementations with universal reference:
template <typename T>
void doWork(T&& param) // forward => copy and move
{
// ops and exprs using std::forward<T>(param)
}
Run Code Online (Sandbox Code Playgroud)
关键是当我们采用右值引用时,我们知道我们有一个右值,所以我们应该std::move保留它是一个右值的事实.当我们采用通用引用(T&&其中T是推导类型)时,我们希望std::forward保留它可能是左值或右值的事实.
所以问题是:既然 …
c++ rvalue-reference move-semantics perfect-forwarding c++11
当我们希望它访问该类的私有成员时,我们将非成员函数作为类的朋友.这赋予它与静态成员函数相同的访问权限.两种选择都会为您提供一个与该类的任何实例无关的函数.
什么时候必须使用朋友功能?什么时候必须使用静态函数?如果两者都是解决问题的可行方案,那么我们如何权衡它们的适用性呢?是否有一个默认情况下应该首选?
例如,当实现一个工厂创建foo只有私有构造函数的类的实例时,工厂函数应该是foo(你会调用foo::create())的静态成员还是应该是友元函数(你会调用create_foo())?
我是 发现我不能用 作为g ++ 4.7的有效标识符,即使-fextended-identifiers启用了该选项:
int main(int argc, const char* argv[])
{
const char* = "I'm very happy";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
main.cpp:3:3:错误:stogram'\ 360'在程序
main.cpp中:3:3:错误:stray'\ 237'在程序
main.cpp中:3:3:错误:stray'\'230'in程序
main.cpp:3:3:错误:在程序中迷路'\ 203'
经过一些谷歌搜索后,我发现标识符中尚不支持UTF-8字符,但通用字符名称应该有效.所以我将我的源码转换为:
int main(int argc, const char* argv[])
{
const char* \U0001F603 = "I'm very happy";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
main.cpp:3:15:错误:通用字符\ U0001F603在标识符中无效
所以显然不是有效的标识符字符.但是,该标准特别允许来自10000-1FFFD附件E.1 范围内的字符,并且不允许它作为E.2中的初始字符.我的下一个努力是看看是否有任何其他允许的unicode字符工作 - 但我没有尝试过.甚至不是重要的PILE OF POO()角色.
那么,为了有意义和描述性的变量名称,给出了什么?请问-fextended-identifiers这样做,因为它会公布或不?它是否仅在最新版本中得到支持?其他编译器有什么样的支持?
我正在为Java程序组建一个开发环境,在第一次尝试我的Ant构建脚本后,我收到了这个错误:
Unable to locate tools.jar. Expected to find it in /usr/lib/jvm/java-6-openjdk/lib/tools.jar
Run Code Online (Sandbox Code Playgroud)
虽然jdk的路径是正确的,但tools.jar确实不存在.它实际上是应该在那里还是我得到一些配置/安装的东西错了?
标准究竟如何定义,例如,float (*(*(&e)[10])())[5]声明一个类型的变量"引用指向函数的10指针的数组()返回指向5 float" 数组的指针?
我知道c ++中的以下情况,其中将调用复制构造函数:
当为现有对象分配其自己的类的对象时
MyClass A,B;
A = new MyClass();
B=A; //copy constructor called
Run Code Online (Sandbox Code Playgroud)如果函数接收作为参数,按值传递,则为类的对象
void foo(MyClass a);
foo(a); //copy constructor invoked
Run Code Online (Sandbox Code Playgroud)当函数返回(按值)类的对象时
MyClass foo ()
{
MyClass temp;
....
return temp; //copy constructor called
}
Run Code Online (Sandbox Code Playgroud)请随时纠正我所犯的任何错误; 但是如果有任何其他情况需要调用复制构造函数,我会更好奇.
我已经看到了其他类似的问题,并阅读了有关它的缺陷.但我仍然没有得到它.为什么i = ++i + 1在C++ 11中定义得很好i = i++ + 1?该标准如何明确定义?
通过我的工作,我在图之前有以下顺序(其中箭头表示关系之前的顺序,除非另有说明,否则一切都是值计算):
i = ++i + 1
^
|
assignment (side effect on i)
^ ^
| |
?i ++i + 1
|| ^
i+=1 |
^ 1
|
?assignment (side effect on i)
^ ^
| |
i 1
Run Code Online (Sandbox Code Playgroud)
我i用黑星标记了一个副作用,i用白星计算了一个值.这些似乎相互之间没有相应的顺序(根据我的逻辑).标准说:
如果对标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值进行的值计算未被排序,则行为未定义.
缺陷报告中的解释并没有帮助我理解.左值到右值的转换与任何事情有什么关系?我弄错了什么?
C和C++开发人员使用短语"通过引用传递",但它们似乎用于表示不同的东西.每种语言中这个模棱两可的短语究竟有什么区别?
c++ ×9
c++11 ×6
ant ×1
c ×1
class ×1
constructor ×1
declaration ×1
g++ ×1
gcc ×1
java ×1
standards ×1
terminology ×1
tools.jar ×1
types ×1
unicode ×1
visual-c++ ×1