在41.2.1 Memory Location他的新书中,B.Stroustrup写了以下内容:
考虑两个全局变量b和c:
Run Code Online (Sandbox Code Playgroud)// thread1 char c = 0; void f() { c = 1; int x = c; } // thread2 char b = 0; void g() { b = 1; int y = b; }现在,x == 1和y == 1,正如任何人所期望的那样.为什么这甚至值得说?考虑如果链接器在内存中的同一个字中分配c和b并且(像大多数现代硬件一样)机器无法加载或存储小于单词的任何内容,可能会发生 什么:
如果没有定义明确且合理的内存模型,线程1可能会读取包含b和c的单词,更改c,并将单词写回内存.同时线程2可以用b做同样的事情.然后,无论哪个线程设法首先读取该单词,哪个线程设法将其结果写回内存最后将确定结果.我们可能会得到10,01,或11 (而不是00).记忆模型使我们免于混乱; 我们得到 11.00不能发生的原因是在任一线程启动之前(由编译器或链接器)完成b和c的初始化. …
n3797中第8.5.3/5段:
对类型"cv1 T1"的引用由类型"cv2 T2"的表达式初始化,如下所示:
如果引用是左值引用和初始化表达式
是左值(但不是位域),"cv1 T1"与"cv2 T2"引用兼容,或者
具有类类型(即,T2是类类型),其中T1与T2不是引用相关的,并且可以转换为类型为"cv3 T3"的左值,其中"cv1 T1"与"cv3"引用兼容T3"(通过枚举适用的转换函数(13.3.1.6)并通过重载决策(13.3)选择最佳转换函数来选择此转换),
...
英语不是我的母语,但在我看来,粗体这个短语(我的重点)给出了T1可以转换为cv3 T3类型左值的想法,我认为这是不正确的.根据我的理解,T2是必须转换为cv3 T3的类型,例如:
struct B : A { operator int&(); } b;
int& ir = B();
Run Code Online (Sandbox Code Playgroud)
显示.
在他的新书"TCPL"的第10.4.3节中,B.Stroustrup写道:
可以在常量表达式中使用足够简单的用户定义类型.例如:
Run Code Online (Sandbox Code Playgroud)struct Point { int x,y,z; constexpr Point up(int d) { return {x,y,z+d}; } constexpr Point move(int dx, int dy) { return {x+dx,y+dy}; } // ... };具有constexpr构造函数的类称为文字类型.为了简单到constexpr,构造函数必须有一个空体,所有成员必须由可能的常量表达式初始化.例如:
constexpr Point origo {0,0};
由于以下原因,这似乎让我感到困惑:
struct Point 没有用户定义的构造函数,它的隐式默认构造函数也不是constexpr.constexpr Point origo {0,0};由于标准(N3337)第7.1.5/9段关于使用constexpr对象声明和第8.5.1/7段有关汇总初始化的汇编而编制.它与constexpr构造函数无关.第3.1 / 2节说,不透明枚举声明是不是定义的声明。但是,它占用内存空间。将其与也具有大小的类定义进行比较。两者都是标准的完整类型。为什么一个是声明,另一个是定义?
#include <iostream>
enum A : int; // opaque-enum-declaration
class B{}; // a class definition
int main() {
std::cout << sizeof(A) << '\n';
std::cout << sizeof(B) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出量
4
1个
编辑
enum A : int;据我所知,下面的不透明枚举声明已定义。
#include <iostream>
enum A : int; // opaque-enum-declaration
int main() {
A a;
std::cout << a << '\n';
}
Run Code Online (Sandbox Code Playgroud)
编辑1
就变量a而言,先前的代码段与下面的代码段没有区别。它们都使变量未定义。因此,很难接受那enum : int;是一个声明和enum A : int {quick, brown, fox}; …
该标准的引用表示赞赏.
#include <iostream>
namespace X {
class A {};
}
template <typename T>
inline T const& max(T const& a, T const& b, T const& c)
{
return max(max(a, b), c);
}
inline X::A const& max(X::A const& a, X::A const& b)
{
std::cout << "non-template" << '\n';
return a;
}
int main()
{
X::A a, b, c;
max(a, b, c);
}
namespace X {
template <typename T>
inline T const& max(T const& a, T const& b)
{
std::cout << "template" << …Run Code Online (Sandbox Code Playgroud) c++ templates language-lawyer argument-dependent-lookup c++11
[class.conv.ctor]/2中的示例包含以下初始化:
Z a3 = Z(1); // OK: direct initialization syntax used
Run Code Online (Sandbox Code Playgroud)
这怎么被认为是直接初始化语法?
C++ 11标准中的哪个地方说它char* p = "abc";是不正确的?
这个例子(void function f(string& s1, string& s2))取自B.Stroustup新书"TCPL"第4版的第297/298页.
#include <iostream>
#include <functional>
#include <string>
#include <algorithm>
void f(std::string& s1, std::string& s2)
{
std::function<void(char* b, char* e)> rev =
[&](char* b, char* e) { if (1<e-b) { std::swap(*b,*--e); rev(++b,e); } };
rev(&s1[0],&s1[0]+s1.size());
rev(&s2[0],&s2[0]+s2.size());
}
int main()
{
std::string s1("Hello");
std::string s2("World");
f(s1, s2);
std::cout << s1 << " " << s2 << '\n';
}
Run Code Online (Sandbox Code Playgroud)
代码编译并打印出正确的结果,即函数f反转输入字符串的字符.节目输出:
olleH dlroW
我可以理解下面表达式的语义.我的问题是接受它的语法,因为变量rev是根据它自己定义的.
std::function<void(char* b, char* e)> rev =
[&](char* b, char* …Run Code Online (Sandbox Code Playgroud) 请考虑以下代码段:
#include <iostream>
struct A { int i; using Int = int; };
int main()
{
std::cout << sizeof(A::Int) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
它在clang和GCC中正常编译和执行.我知道这看起来很明显,但我在标准(C++ 14)中找不到任何支持引用A::Int的内容main().