语言/CPP {CPP错误汇总}
@LOC: 2
汇总
三元运算符b ? "aa" : 3
这是错误的, 因为"aa" 和 3
的类型不同;
未初始化所導致的錯誤
當發生很詭異/莫名其妙的錯誤時, 大概率是因為有變量沒有初始化的緣故;
比如對於一個函數, 控制的變量 是完全相同的 反而得到了不同的結果, 大概率是沒有初始化, 比如void F(){ int i; ...}
第一次調用函數 一般此時i==0
(會得到預期答案), 但第二次以後i
就是隨機值;
&,^,|
运算符的优先级 小于==
if( edge^1 == _faEdge)
这是错误的, 他等价于if( edge ^ (1==_faEdge)
;
运算符优先级: ==
等于
>
>
> & ^ |
位运算
>
>
> && ||
逻辑
下標越界是合法的…
@MARK: @LOC_1
;
@LINK: https://www.acwing.com/problem/content/submission/code_detail/28370736/
;
此时报错说是在Query
函数里的报警;
如果你把163
行的ASSERT_( __NodesCount < __NodesMaximum_);
放到160
行, 即放到if
的前面, 那么会报错会变成 你160
行的这Insert
函数里的;
而这一前一后 有什么区别吗? 按理说完全没问题; 這就非常玄學???
難道是因為(CPU的指令序順序的調整)? 但是即便順序調整 你的這個ASSERT
報警 是一定會執行的 不會消失的呀;
其實 你仔細思考一下, 你這一前一後 區別在哪? 就完全在於 多執行了一個 你中间的那个if
; (從現象來看 你肯定是修改了NodesCount
這個變量 一定是的 否則這一前一後本質是完全相同的, 即本來NodesCount == NodesMaximum
可以 你修改成了比如NodesCount = -1
);
即__Nodes[ __NodesCount] = ?
, 可是此時已經下標越界了 那麼 這個?
是賦值了給誰呢? 給到了(下一個內存位置), 此時我們看你的變量定義:
int __Nodes[ __NodesCount];
int __NodesCount;
因此 實際上 你執行了NodesCount = ?
, 即你修改了他;
可以證明一下 即把他倆互換位置 即讓NodesCount
在Nodes
的前面, 你會發現 一切正常了;
@DELI;
把問題簡化一下 即:
int A[10];
int Ind;
Ind = 10;
if( true){
A[ind] = -1; // 等價於是`Ind = -1`;
}
ASSERT_( ind < 10);
A[ind] = 55;
因此, 不要下標越界, 即 你的ASSERT_( ind < 10)
要寫在if
的前面;
remove_rv< T>
是错误的
比如
两个类之间相互调用
MARK: @LOC_0
;
class A{
void FA( B _b){ ...}
}
class B{
void FB( A _a){ ...}
}
此时FA
会报错, 因为他找不到B
这个类的定义;
1: 你需要在class A{
的上一行 写成class B;
声明;
.
但是 此时仍然是错误的, 因为你访问_b.xxx
这个xxx
是找不到的, 因为上面只有class B;
这个声明 而他里面具体的定义是找不到的;
因此, 正确做法是:
class B;
class A{
void FA( B);
}
class B{
void FB( A _a){ ...}
}
void A::FA( B _b){ ...}
T &
与const T &
传参的区别 不只是修改
F( T &), FF( const T &)
你可能认为: F可以修改, FF不可以修改, 这就一点区别;
其实不是的, 还有个非常重要 且容易忽略的性质: const &
还可以接收临时变量(即右值), 比如说 你的参数是个右值 那么F函数一定会报错 而FF函数是没问题的;
容器一旦修改 当前迭代器就失效了
for( const auto & i : mp){
ANS += mp[x]; // `x`可能不存在
}
这是错误的, 如果x
这个键是不存在的 则你是在添加新元素! 那么你当前所循环的迭代器就失效了 这是非常严重的错误, 你迭代器加const
也不行 因为const
只是表示对迭代器不可以修改 但是此时你容器已经改变了 迭代器已经失效了!
.
比如 [1,2]
, 第一次遍历到1 使用了3 也就是插入了3, 那么下一个遍历 可能就不是2 (也可能不是3) 也可能就直接循环结束了 (也就是, 并不会正常的遍历);
所以, 不要以为只是增加时间复杂度的问题, 而是程序出错的问题;
比如, 已知所有的mp[?] > 0
, 那么你可能认为 我们即便使用不存在的键 无非就是把他设置了mp[x] = 0
并不会影响答案, 只是增加了复杂度而已;
.
确实不会影响答案, 但是 你的遍历就乱套了 整个过程并不是你想象的那样 (容器一旦修改 迭代器就失效了! 这是非常严重的错误);
因此 一定要进行if( mp.find( x) != mp.end()){ ...}
的判断, 只有他是存在于容器中时 再访问他 (这样就不会插入新元素了); (非常重要!)
例题: LINK: https://editor.csdn.net/md/?not_checkout=1&articleId=131933499
;
初始化列表 不可以使用emplace_back
vector< vector<int> > A
, 需求是往里面添加一个vector<int>{1,2,3}
的对象;
使用A.emplace_back( 1, 2, 3)
是错误的, 因为vector<int>
并没有一个 形如vector( int, int, int)
的构造函数;
.
vector< T>::emplace_back( a,b,c)
的本质, 就是调用T(a,b,c)
的构造函数;
使用A.emplace_back( {1,2,3})
是错误的;
.
很容易认为这是正确的, 因为vector<int>( {1,2,3})
是正确的; 只能说 这个构造函数 并不是正统的, 因为他接收的是初始化列表;
.
所以这很特别, 这种用法是不可以的;
正确的是: A.push_back( {1,2,3})
;
不要让宏作运算
#define M_( _a, _b) _a * _b * _b
;
当你使用M_( x - 1, y - 1)
时, 他是x - 1*y - 1*y - 1
; 解决方法是 M_( _a, _b) (_a)*(_b)*(_b)
;
但你还会遇到问题, 比如M_( f(x), f(y))
, 此时你的f(y)
会执行2次, 你的本意是 让f(y)
执行1次 只是他的返回值 执行2次, 因此 这也会出错;
因此, 宏定义 就让他做简单的文本替换的功能, 不要做运算;
全局容器变量要初始化
vector< int> A[10];
int main(){
...
}
A[i]
maybe not Empty!
You should operate A[i].clear()
;
%0
模数为0
x % 0
Eroor: remainder by zero is undefined;
(*P)[M]
二维指针的地址
constexpr int M = 10;
int x = 3;
T (*a)[ 10] = new T[ x][ 10];
a09 a19 a29
... ... ...
a02 a12 a22
a01 a11 a21
a00 a10 a20
If you wanna locate at the element ai0
, the pointer a + i * M
is Wrong! cuz the type of a
is T (*)[M]
, not T *
;
.
That is, the pointer a + i
denotes the array ai0, ai1, ai2, ..., ai9
, therefor a + i
is the address of the element ai0
;
.
If you have another pointer b = &a00
, then b + i * M
corresponds to ai0
;
1 < a < 3
if( 1 < a < 3){ ...}
這個代碼是錯誤的, 他會是: 1<a
會變成一個0/1
的布爾值b 然後b < 3
;
正確代碼是if( 1<a && a<3){ ...}