在C++ 14中给出以下代码:
void foo() {
double d = 5.0;
auto p1 = new int[d];
}
Run Code Online (Sandbox Code Playgroud)
clang在没有诊断的情况下编译它,而另一方面gcc产生以下诊断(见它在godbolt中生活):
error: expression in new-declarator must have integral or enumeration type
7 | auto p1 = new int[d];
| ^
Run Code Online (Sandbox Code Playgroud)
我特意标记了这个C++ 14,因为在C++ 11模式下,clang将其视为格式不正确并产生以下诊断(请参阅godbolt中的内容):
error: array size expression must have integral or unscoped enumeration type, not 'double'
auto p1 = new int[d];
^ ~
Run Code Online (Sandbox Code Playgroud)
clang是否正确?如果是这样,在C++ 14中有什么改变允许这个?
基本上,为什么这是有效的:
auto p1 = new int[10]{5};
但这不是:
auto p1 = new int[10](5);
更一般地说,new-expression初始化程序的规则是什么?
我找到了以下内容:
- 如果省略new-initializer,则默认初始化对象(8.5).[注意:如果未执行初始化,则对象具有不确定的值. - 结束注释] - 否则,根据8.5的初始化规则解释new-initializer以进行直接初始化.
那么第二种情况是无效的,因为smth就像T((5))是无效的(从表达式直接初始化(5))?或者是什么原因?
编辑:好吧,我对(())事物的建议似乎很愚蠢,因为我认为没有理由为什么只应用于数组new-expression.
我想知道表单的表达式new super.SomeProperty在JavaScript中是否有效.
在处理跨浏览器行为不一致的代码时出现了这个问题,例如下面的代码段中的示例.
class Test {
test() {
return new super.constructor;
}
}
console.log((new Test).test());Run Code Online (Sandbox Code Playgroud)
这会在Firefox和Edge中打印一个空对象,但会ReferenceError在Chrome和一个SyntaxErrorSafari中抛出一个.错误可以很容易地绕过括号super.constructor或使用变量,因此它不是一个真正的限制,而是对语言本身的好奇心.我检查了规范,但是在这种情况下找不到任何暗示应该抛出错误的东西,所以很可能我错过了什么.
javascript specifications super referenceerror new-expression
我们知道它void*没有关于它指向的数据的实际类型的信息。但是,从 cppreference 开始new,new[]我们知道这些运算符返回void*. 那么,如何给出:
auto x = new int{};
Run Code Online (Sandbox Code Playgroud)
知道new操作符应该返回void*,x被推导为一种类型int*,不是void*吗?
再考虑一个例子:
struct foo {
static void* operator new(std::size_t n) {
std::cout << "new called!\n";
return ::new char[n];
}
};
Run Code Online (Sandbox Code Playgroud)
让我们添加一些牛逼YPE d isplayer:
template <typename T>
struct TD;
Run Code Online (Sandbox Code Playgroud)
和测试代码:
int main() {
auto x = new foo{};
TD<decltype(x)>{};
}
Run Code Online (Sandbox Code Playgroud)
代码无法编译,错误指示decltype(x)是foo*。如果我们注释掉 的最后一行main,我们就会知道我们的void*-returning 操作符会因为new …
有人可以向我解释 C++ 入门第 5 版中的这一段:
术语:新表达式与运算符新函数
库函数operator new 和operator delete 被误导了。与其他运算符函数(例如 operator=)不同,这些函数不会重载 new 或 delete 表达式。事实上,我们不能重新定义 new 和 delete 表达式的行为。
new 表达式总是通过调用 operator new 函数来获取内存,然后在该内存中构造一个对象来执行。删除表达式总是通过销毁对象然后调用操作符删除函数来释放对象使用的内存来执行。
通过提供我们自己对 operator new 和 operator delete 函数的定义,我们可以改变内存的分配方式。但是,我们无法更改 new 和 delete 运算符的基本含义。
我没有看到operator neworoperator delete与任何其他重载运算符(如赋值运算符)之间的区别=。那么“被误导性命名”是什么意思?并且我们都知道我们不会像这样覆盖表达式,fObj + fObj但是我们会重载运算符而不是表达式本身。
事实上,我发现这一段本身具有误导性。毕竟我们可以“滥用”任何可重载运算符以及来自哪个运算符new,delete那么他在这一段中的意思是什么?谢谢!