以下代码在C++ 11中是否合法?
int16_t x {0xaabb};
int64_t xxxx {0xaaaabbbbccccdddd};
Run Code Online (Sandbox Code Playgroud)
代码来自"The C++ Programming Language"第4版(第150页).
我们知道,列表初始化不允许缩小转换,在标准缩小转换的定义中,我们有:
缩小转换是一种隐式转换
- [...]
- 从整数类型或无范围枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式,而后是实际值转换将适合目标类型,并在转换回原始类型时生成原始值.
检查缩小转换对样本代码的规则中,我认为该示例代码是因为违法0xaabb
而0xaaaabbbbccccdddd
不能代表int16_t
和int64_t
分别.那是对的吗?
但我不太明白措辞"除了源是一个常量表达式,转换后的实际值将适合目标类型,并在转换回原始类型时产生原始值".我想知道在什么情况下转换后的实际值不适合目标类型.由于整数类型之间的转换始终有效(尽管在目标类型已签名并且源值无法在目标类型中表示的情况下实现定义,但无论如何它都不是未定义的行为),"值是否始终为真" 后转换将适合目标类型"?从这个角度来看,我开始质疑我对示例代码缩小转换的判断.如果是这种情况,为什么标准在某种情况下总是如此?为什么不说"除了源是一个常量表达式,转换后的实际值在转换回原始类型时会产生原始值"?
有人可以帮我澄清一下吗?谢谢!
class AAA {
public:
explicit AAA(const AAA&) {}
AAA(int) {}
};
int main() {
AAA a = 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,据我所知,虽然在大多数情况下已经省略,但仍然需要在语义上调用复制构造函数.我的问题是,呼叫是明确的还是隐含的?很长一段时间,我在脑海中得出结论,调用AAA::AAA(int)
是隐式的,但是对复制构造函数的调用不是.今天我偶然得到了g ++来编译上面的代码并报告错误.(VC12编译正常.)
在标准的第8.5节中:
如果目标类型是(可能是cv限定的)类类型:
如果初始化是直接初始化,或者它是复制初始化,其中源类型的cv-nonqualified版本与目标类相同的类或派生类,则考虑构造函数.列举了适用的构造函数(13.3.1.3),并通过重载解析(13.3)选择最佳构造函数.调用所选的构造函数来初始化对象,初始化表达式或表达式列表作为其参数.如果没有构造函数适用,或者重载决策是不明确的,则初始化是错误的.
否则(即,对于剩余的复制初始化情况),可以如13.3中所述枚举可以从源类型转换为目的地类型或(当使用转换函数时)到其派生类的用户定义的转换序列. 1.4,通过重载决策(13.3)选择最好的一个.如果转换不能完成或不明确,则初始化是错误的.选择的函数以初始化表达式作为参数调用; 如果函数是构造函数,则调用初始化目标类型的cv-nonqualified版本的临时函数.临时是一个prvalue.然后,根据上面的规则,调用的结果(对于构造函数的情况是临时的)用于 直接初始化作为复制初始化目标的对象.在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除此直接初始化中固有的复制; 见12.2,12.8.
direct-initialize
上面引号中的粗体表示对复制构造函数的调用是明确的,对吧?是g ++错误还是我对标准的解释错了?
class AAA {
public:
AAA() {}
AAA(const AAA&) {}
};
class BBB {
public:
BBB() {}
operator AAA() { AAA a; return a; }
};
int main() {
BBB b;
AAA a = {b};
}
Run Code Online (Sandbox Code Playgroud)
上面的代码编译在g ++和vc ++上,但不是clang ++.
传统的语法AAA a = b;
在这三个方面都可以正常编译.
class AAA {};
class BBB {
public:
BBB() {}
operator AAA() { AAA a; return a; }
};
int main() {
BBB b;
AAA a = {b};
}
Run Code Online (Sandbox Code Playgroud)
上面的代码不能在g ++,vc ++,clang ++中编译.与第一个代码片段的唯一区别是我删除了两个用户提供的AAA构造函数.
同样,传统语法AAA a …
在8.4.2 Explicitly-defaulted functions [dcl.fct.def.default]
标准中,
显式默认函数和隐式声明函数统称为默认函数,实现应为它们提供隐式定义(12.1 12.4,12.8),这可能意味着将它们定义为已删除.如果特殊成员函数是用户声明的,并且在其第一个声明中未明确默认或删除,则由用户提供.用户提供的显式默认函数(即,在第一次声明后显式默认)是在明确默认的位置定义的; 如果将这样的函数隐式定义为已删除,则该程序格式错误. [注意:在第一次声明后将函数声明为默认值可以提供高效的执行和简洁的定义,同时为不断发展的代码库启用稳定的二进制接口.-结束语]
最后的注释是什么意思?从我所看到的,在第一次声明之后将函数声明为默认将使用户提供的函数,从而使函数变得非常简单,因此要么使类型具有非平凡的默认构造函数,要么使类型非常简单-copyable,当然使类型非平凡和非POD,同时仍然具有提供函数实际定义的实现.但我不明白这是如何导致" provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base
"的.任何想法都是受欢迎的,现实世界的例子受到高度赞赏.谢谢.
这种类型的一个例子:
struct A {
A();
};
A::A() = default;
Run Code Online (Sandbox Code Playgroud) 在C++编程语言C++第4版第6.2.6节中,它说:
允许R,L和u前缀的组合,例如,uR"**(foo \(bar))**".请注意字符(无符号)和字符串UTF-32编码(第7.3.2.2节)的U前缀含义的显着差异.
我不太明白作者在这里想说的是什么.确实是什么"戏剧性的差异"?为什么这里使用"(unsigned)"这个词?
根据我的理解,带U前缀的字符文字包含引用字符的ISO-10646代码点值,它基本上与字符串文字的U前缀相同,并且与"unsigned"的概念无关. ".
几天前,我问了一个关于类内定义的友元函数范围的问题(类中定义的朋友函数属于哪个范围?),我知道该函数属于封闭命名空间,但在类外部显式声明之前不会被搜索(ADL是一个例外).
今天我在C++标准(第11.3节)中找到了一些相关的陈述:
当且仅当该类是非本地类(9.8),函数名称是非限定的,并且该函数具有命名空间范围时,才能在类的友元声明中定义函数.[例如:
Run Code Online (Sandbox Code Playgroud)class M { friend void f() { } // definition of global f, a friend of M, // not the definition of a member function }; —end example ]
这种功能是含蓄的
inline
.在类中定义的友元函数位于定义它的类的(词法)范围内.在类外定义的友元函数不是(3.4.1).
我们可以看到这里有两个与范围相关的语句:"具有命名空间范围"和"位于定义它的类的(词法)范围内".我在这里很困惑.如果前者与我之前的问题(一个类内定义的朋友函数属于哪个范围?)有关,那么后者代表什么?
在C++中,qsort()
标准库提供了两个版本:
extern "C" void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
extern "C++" void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
Run Code Online (Sandbox Code Playgroud)
bsearch()
差不多.
我的问题是,调用时重载解析如何工作qsort()
?它是否根据作为最后一个参数传递的函数指针的链接类型("C"或"C++")自动链接到相应的函数?或者调用者需要使用某种额外的语法明确指定?
(让我们放下诱惑,呼唤std::sort
一秒......)
标准中提到了很多与字符集相关的概念:基本源字符集,基本执行字符集,基本执行宽字符集,执行字符集和执行宽字符集:
我对基本源字符集,基本执行字符集和基本执行宽字符集没有太多疑问.
至于执行字符集,标准表示它是实现定义的和特定于语言环境的,所以我试着通过观察字符串文字初始化的char数组的字节内容来获得一些真正意义,该数组的值应该等于数值的执行字符集中字符的编码(由于多字节编码,通用字符名称可能映射到多个char元素):
char str[] = "Greek lowercase alpha is: \u03B1.";
Run Code Online (Sandbox Code Playgroud)
它似乎在Linux上几乎总是utf-8(CE B1
存储在希腊字母的数组中).在Windows上,如果系统区域设置为英语(3F
由于希腊语在Windows-1252中不可用而存储了一些错误的值),则为Windows-1252;对于其他语言A6 C1
环境,则为某些其他编码(例如,在cp936中为中文语言环境,E1
在Windows-1253中为希腊语locale,分别代表这两种编码中的希腊小写字母alpha).对于希腊字母在区域设置中可用的所有情况(因此在执行字符集中可用),cout << str;
可以适当地打印希腊字母.一切似乎都没问题.
但对于执行宽字符集,我不太了解.它在主要平台上的确切编码是什么?似乎0x3B1
希腊小写字母alpha 的ISO-10646值总是存储在wchar_t
我尝试的所有平台上的下面的声明中:
wchar_t wstr[] = L"Greek lowercase alpha is: \u03B1.";
Run Code Online (Sandbox Code Playgroud)
所以我猜执行宽字符集可能是UCS-2/UTF-16或UTF-32(不同的环境有不同的大小wchar_t
,4用于Linux,2用于Windows)?但是,wcout << wstr;
不能在Linux或Windows上正确打印希腊字母.当然,执行宽字符集的成员和编码是实现定义的,但这对于实现提供的iostream
工具来说不应该是一个问题,以便正确地识别和处理它,对吧?(虽然执行字符集也是实现定义的,但iostream
设施可以正常处理它.)wchar_t
当由iostream
设施处理时,数组的默认解释是什么?(无论如何,只是为了澄清,我对执行宽字符集的本质更感兴趣,而不是找到在某些平台上打印宽字符串的正确方法.)
PS:我是新手wchar_t
,所以我道歉,如果我说错了.
template <typename T>
class A {
public:
template<class C> A(const A<C>&) {}
A(A&&) {}
};
void f(A<int>& a)
{
A<int> b(a);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码不能在g ++/clang ++中编译报告复制构造函数因为用户提供的移动构造函数而被删除(尽管vc ++编译好了).是否有任何标准要求阻止在重载解析期间选择模板构造函数(我知道它不是复制构造函数)?或者是否要求初始化程序与initializee具有相同的类型时,它必须选择复制构造函数?
在Android Studio的Preferences
- > Appearance & Behavior
- > System Settings
- >中Updates
,我尝试启用该Use secure connection
选项:
但是当我点击Apply
按钮时,出现错误"Secure connection is not supported on Java 6"
:
我检查了JDK位置设置Project Structure
,它是/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home
:
我似乎在使用Java 7,而不是Java 6.那么为什么安全连接设置抱怨Java 6不支持?
第一个1.6.0.jdk
来自Apple,另外三个来自Oracle.