Sayeth C++ 标准:
该声明的点的名称是立即其完整的说明符后,其之前 初始化(如果有的话)... [basic.scope.pdecl]
也就是说,一个变量在其自身的初始化表达式的上下文中,并且可以被引用。
据我所知,你可以用它做以下类型的事情:
int x = x,这是格式良好但毫无意义。void* p = &p,这很可爱但没用。std::any a {&a},#2 的 C++17 版本。MyClass m {std::move(m)}中,C ++ 11版本的#1和可能UB莫名其妙。MyClass m {myFunc(m)},用一个函数来获取你未初始化的对象,我想把它记录在某个地方?并返回一些值,以便构造函数可以试一试。#1-4当然没用。似乎可以构建一个接口,其中 #5 有意义,但我认为它不是完成任何事情的最直接方式。由于在评估初始化程序时新变量尚未初始化,因此读取其值是无用/非法的,并且其地址通常对其初始化并不重要。
(对于将声明点保留到初始化器之后,可以提出一个稍微强一点的案例:int avg = avg(a,b,c)。这不是好的代码,它对任何事情都不是必需的,但它比void* p = &p.更有意义。)
但这不仅仅是关于用例。通常,C++ 会煞费苦心地阻止访问未初始化的对象。例如,它一次设置一个对象的 vtable 一个基类:如果 D 继承自 C 继承自 B,则在 C 的构造函数期间,虚方法将被分派给 C 的实现,而不是 D 的实现。可以查看未初始化对象的常见情况是这种情况,以及(更常见的问题)this在成员初始值设定项表达式中的使用。
因此,我看不到在其初始化程序之前将名称带入范围的用途,并且我可以看到将其延迟到初始化程序之后的明确理由(Stroustrup 也会看到)。鉴于此,C++ 选择的行为是否有明确的点?
#include<stdio.h>
void main(){
printf("%f\n",5/9); // prints 0.000000
printf("%f\n",9.0/5.0); // prints 1.800000
printf("%f\n",5/9); // prints 1.799999
}
Run Code Online (Sandbox Code Playgroud)
第 5 行值应像第 3 行一样打印 0.000000
我在本地机器和在线编译器中尝试过,结果是相同的
我有一个向量:
std::vector<int> vec = {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
我想做一个反向for循环。它有效,当我写:
for(int i = vec.size() - 1; i >= 0; --i) {
std::cout << i << std::endl; // 2, 1, 0
}
Run Code Online (Sandbox Code Playgroud)
但是如果我这样写,我会得到一个非常大的数字(比如 18446744073709223794):
for(size_t i = vec.size() - 1; i >= 0; --i) {
std::cout << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是当我写的时候它们都有效:
for(int i = 0; i < vec.size() - 1; ++i) {
std::cout << i << std::endl; // 1, 2, 3
}
// Or
for(size_t i = 0; i < …Run Code Online (Sandbox Code Playgroud) void func( int radius ) { ... }
Run Code Online (Sandbox Code Playgroud)
这是这样调用的:
func( 12.4 ); // by user expecting the float to be processed, not realizing there's an implicit conversion
Run Code Online (Sandbox Code Playgroud)
在这种情况下,有没有办法从编译器或运行时环境中获得警告?
#include <iostream>
using namespace std;
void aa(int n) {
int test[n] = {0};
}
int main() {
aa(10);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并得到
error: variable-sized object may not be initialized
Run Code Online (Sandbox Code Playgroud)
但
#include <iostream>
using namespace std;
void aa(int n) {
int test[n];
fill(test,test+10,0);
}
int main() {
aa(10);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
还可以
我想知道为什么在前一个失败的情况下编译该文件的原因。
我试图 printf 一个简单的字符串,但我不能。
#include <stdio.h>
int main(){
char *word;
scanf("%s", &word);
printf("%s\n", word);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我插入这个词时,我的代码会中断。
它只是停止程序执行,但没有给我任何错误。
我究竟做错了什么?
考虑这个代码片段
#include <iostream>
int foo() {
int a;
return a;
}
int main() {
auto &&ret = std::move(foo());
std::cout << ret;
}
Run Code Online (Sandbox Code Playgroud)
使用ASAN编译g++ -fsanitize=address -fno-omit-frame-pointer -g -std=c++17 main.cpp -o main,运行./main显示错误
==57382==ERROR: AddressSanitizer: stack-use-after-scope on address 0x00016b3cb480 at pc 0x000104a37e68 bp 0x00016b3cb450 sp 0x00016b3cb448
READ of size 4 at 0x00016b3cb480 thread T0
#0 0x104a37e64 in main main.cpp:8
#1 0x104a75084 in start+0x200 (dyld:arm64e+0x5084)
Run Code Online (Sandbox Code Playgroud)
但是如果我在 auto 之后删除引用,这段代码可以编译并运行,而不会出现 ASAN 给出的错误。我不明白的是,如果std::move返回对给定对象的引用,那么该对象(foo()在本例中是临时创建的)将在函数调用返回后被销毁std::move,因此无论它是绑定到右值引用还是分配给新值应该无效,因为该临时值在移动操作后已经被销毁,对吗?那么为什么 ASAN 在第二种情况下不会给出错误。
- - …
我对C编程非常陌生,并且遇到了一个小问题。
我输入0.05作为双精度浮点数,并通过我的解决方案图片中给出的公式运行它,以获取答案0.06242。但是,无论输入什么内容,我都会不断得到0.000000。有人可以向我解释我的代码是否有问题,或者可以解释我在scanf和printf中是否正确使用“%lf”?谢谢。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
main(){
double guess, pow1,pow2,pow3, estimate;
printf("Type in an initial guess of the root(for this case type 0.05): ");
scanf("%lf", &guess);
printf("Calculating the root estimate using formula from solution...\n");
pow1 = pow(guess, 3);
pow2 = 0.165*pow(guess, 2);
pow3 = 3*pow(guess, 2);
estimate = guess - ((pow1 - pow2 + 0.0003993) / (pow3 - 0.33*guess));
printf("Estimate = %lf\n", estimate);
}
Run Code Online (Sandbox Code Playgroud) 为什么下面的代码可以编译通过?
class Demo
{
public:
Demo() : a(this->a){}
int& a;
};
int main()
{
Demo d;
}
Run Code Online (Sandbox Code Playgroud)
在本例中,a是对整数的引用。但是,当我初始化 Demo 时,我传递了一个对尚未初始化的整数引用的引用。为什么会这样编译?
即使int我使用对具有私有默认构造函数的类的引用而不是 ,这仍然可以编译。为什么这是允许的?