标签: cpp-core-guidelines

确保() - 指南支持库

我试图了解如何Ensures()在代码中使用.如示例中所示,如果我尝试使用Ensures()如下...

int main(void)
{
    int result = 0;
    // Some calculation
    Ensures(result == 255);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果result变量不等于255,程序将使用以下输出崩溃"terminate called without an active exception".我的问题是如何Ensures()正确使用?

c++ c++11 cpp-core-guidelines guideline-support-library

7
推荐指数
1
解决办法
2991
查看次数

在向量上使用基于范围的循环时,CppCoreChecker C-Style强制警告

假设以下代码:

#include <iostream>
#include <vector>
#include <string>

int main() {
    std::vector<std::string> lines;
    lines.push_back("line");
    for (const auto& s : lines) {
        std::cout << s;
    }
}
Run Code Online (Sandbox Code Playgroud)

在for循环的行中,我收到以下警告:

C26493不要使用执行static_cast downcast,const_cast或reinterpret_cast的C样式转换.

有人可以解释这是从哪里来的吗?我使用Visual Studio 2017 Community Edition版本15.2.

c++ static-analysis c++11 cpp-core-guidelines

7
推荐指数
1
解决办法
288
查看次数

使用模板来提高代码的抽象级别?

我正在浏览CppCoreGuidelines的T.1,并且有以下示例

例1

template<typename T>
    // requires Incrementable<T>
T sum1(vector<T>& v, T s)
{
    for (auto x : v) s += x;
    return s;
}
Run Code Online (Sandbox Code Playgroud)

例2

template<typename T>
    // requires Simple_number<T>
T sum2(vector<T>& v, T s)
{
    for (auto x : v) s = s + x;
    return s;
}
Run Code Online (Sandbox Code Playgroud)

根据上面的指南,这些例子在概念上是不好的,因为它错过了泛化的机会(受限于"可以递增"或"可以添加"的低级概念).

如何表达上述模板才能被称为良好的通用模板?

c++ cpp-core-guidelines

7
推荐指数
1
解决办法
179
查看次数

我什么时候使用"__attribute __((nonnull)""vs"not_null <T*>"?

我习惯于__attribute__((nonnull))在表达不应该为null的指针时使用.

void f(int* ptr __attribute__((nonnull)));

int main(){
    int* ptr = new int(1);
    f(ptr);
}
void f(int* ptr){/*impl*/}
Run Code Online (Sandbox Code Playgroud)

但是,对于GSL,还有not_null<T*>包装类型.
void function1(gsl :: not_null n);

void f(gsl::not_null<int*> n);

int main(){
    int* ptr = new int(1);
    f(ptr);
}
void f(gsl::not_null<int*> n){/*impl*/}
Run Code Online (Sandbox Code Playgroud)

假设有语言设施支持GSL版本,我应该总是not_null<T*>代替__attribute__((nonnull))现在使用吗?

我一直认为编译器属性可能有助于优化,但包装器版本可以解析为未归因的指针.

c++ null attributes pointers cpp-core-guidelines

6
推荐指数
1
解决办法
1916
查看次数

传递span <T>和std :: array作为参数有什么区别?

在他的C++核心指南中,Bjarne Stroustrup建议在通过引用传递数组时使用span.为什么不直接传递一个std :: array对象?

c++ cpp-core-guidelines

6
推荐指数
1
解决办法
2732
查看次数

gsl :: multi_span用于什么?

C ++核心准则提到跨度,而不是“跨度”。但是-我看到Microsoft的GSL实现中有一个multi_span

template <
    typename ValueType,
    std::ptrdiff_t FirstDimension,
    std::ptrdiff_t... RestDimensions
>
class multi_span { ... };
Run Code Online (Sandbox Code Playgroud)

因此,显然这是的某种多维版本gsl::span。但是那是什么意思呢?为什么我们需要这个多维范围,或者更确切地说-我们什么时候使用它?我似乎找不到任何文档。

c++ cpp-core-guidelines

6
推荐指数
1
解决办法
1083
查看次数

为什么 gsl::not_null 确保 get() 上的 ptr 不为 null?

在微软实施指南支持库中我看到以下代码:

template<class T>
class not_null {
    ...
    template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    constexpr explicit not_null(U&& u) : ptr_(std::forward<U>(u)) {
        Expects(ptr_ != nullptr);
    }
    ...
    constexpr T get() const {
        Ensures(ptr_);
        return ptr_;
    }
    ...
    T ptr_;
}
Run Code Online (Sandbox Code Playgroud)

所有gsl::not_null可能采用指针的构造函数都会检查这些指针是否为空,但我们仍然在每次ptr_取消引用时检查指针 ( ) 的存储值是否为空。鉴于在 C++ 中我们通常不会为不需要的东西付费,为什么我们要进行此检查?

UP:确保按如下方式实现(使用默认标志):

#define GSL_LIKELY(x) (!!(x))
...
#define GSL_CONTRACT_CHECK(type, cond)                         \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
...
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
Run Code Online (Sandbox Code Playgroud)

c++ null cpp-core-guidelines guideline-support-library

6
推荐指数
1
解决办法
3778
查看次数

当索引不是整数常量表达式时,不要使用数组下标; 使用gsl :: at()代替

我试图在Microsoft Visual Studio中创建一些示例代码

int main()
{
    const size_t size = 10;
    int arr[size];

    for (size_t i = 0; i < size; ++i)
        arr[i] = i;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在JetBrains ResharperC++发出以下警告 arr[i] = i;

在此输入图像描述 当索引不是整数常量表达式时,不要使用数组下标; 使用gsl :: at()代替

我无法理解这意味着什么以及如何解决此警告.

由于这是我经常使用的方案,我有点担心警告.

任何人都可以建议或指出我正确的方向吗?

编辑:将循环更改为:

for (size_t i = 0; i < size; ++i)
    arr[i] = 0;
Run Code Online (Sandbox Code Playgroud)

仍然会发出警告.

c++ resharper-c++ cpp-core-guidelines

6
推荐指数
1
解决办法
1181
查看次数

了解gsl :: narrow实现

C ++核心原则有一个narrow抛出如果转换改变了值施放。查看该库的microsoft实现

// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
T narrow(U u) noexcept(false)
{
    T t = narrow_cast<T>(u);
    if (static_cast<U>(t) != u)
        gsl::details::throw_exception(narrowing_error());
    if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))  // <-- ???
        gsl::details::throw_exception(narrowing_error());
    return t;
}
Run Code Online (Sandbox Code Playgroud)

我不明白第二个if。它会检查什么特殊情况static_cast<U>(t) != u?为什么还不够?


为了完整性:

narrow_cast只是一个static_cast

// narrow_cast(): a searchable way to do …
Run Code Online (Sandbox Code Playgroud)

c++ casting narrowing c++11 cpp-core-guidelines

6
推荐指数
1
解决办法
1399
查看次数

编译器生成的默认构造函数如何比只初始化成员什么都不做的自写结构更有效?

通过这个答案,我正在阅读核心准则

C.45:不要定义仅初始化数据成员的默认构造函数;改用类内成员初始化器

给出的理由是

原因

使用类内成员初始化器可使编译器为您生成函数。编译器生成的函数可以更有效。

请注意,这是专门针对默认构造函数的,该默认构造函数除了初始化成员外不执行任何操作,并且该准则建议不要编写这样的构造函数。

“坏”的例子是:

Example, bad

class X1 { // BAD: doesn't use member initializers
    string s;
    int i;
public:
    X1() :s{"default"}, i{1} { }
    // ...
};
Run Code Online (Sandbox Code Playgroud)

在该特定示例(或任何其他示例)中,编译器生成的构造函数比用户提供的构造函数更有效率吗?

我天真地希望初始化程序列表提供与类初始化程序相同的优化机会。

c++ initialization default-constructor cpp-core-guidelines

6
推荐指数
2
解决办法
96
查看次数