本文介绍了C ++:向量边界的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我来自Java,目前正在学习C ++。我使用Stroustrup的Progamming原则和使用C ++的实践。我现在正在使用向量。在第117页,他说访问向量的不存在元素将导致运行时错误(与Java相同,索引超出边界)。我使用MinGW编译器,当我编译并运行此代码:

  #include< iostream& 
#include< cstdio>
#include< vector>

int main()
{
std :: vector< int> v(6);
v [8] = 10;
std :: cout<< v [8];
return 0;
}

它给我作为输出10.更有趣的是,如果我不修改不存在的向量元素(我只是打印它期望运行时错误或至少一个默认值),它打印一些大的整数。所以...是Stroustrup错误,还是GCC有一些奇怪的编译C ++的方法?

解决方案

这本书有点模糊。它不是一个运行时错误,因为它是在运行时显示的未定义的行为。这意味着任何事情都可能发生。但错误严格地与,而不是与程序执行,而且事实上不可能也不明智,甚至谈论一个程序的未定义行为的执行。



C ++中没有什么可以防止编程错误,这与Java中不一样。






如@sftrabbit所说, std :: vector 有一个替代接口,,它总是给出一个正确的程序(虽然它可能会抛出异常),因此可以推理。 / p>




让我以一个例子重复一点,因为我相信这是C ++的一个重要的基本方面。假设我们从用户读取一个整数:

  int read_int()
{
std: :cout< 请输入数字:;
int n;
return(std :: cin>> n)? n:18;
}

现在考虑以下三个程序:



危险的一个:此程序的正确性取决于用户输入!这不一定是不正确,但它是不安全的(我将其称为破坏)。

  int main()
{
int n = read_int();
int k = read_int();
std :: vector< int> v(n)。
return v [k];
}

无条件更正:无论用户输入什么,我们知道这个程序的行为。

  int main()try 
{
int n = read_int ();
int k = read_int();
std :: vector< int> v(n)。
return v.at(k);
}
catch(...)
{
return 0;
}

正确的 code> .at()是尴尬。更好地检查和提供反馈。因为我们执行动态检查,所以未经检查的向量访问实际上保证是正常的。

  int main()
{
int n = read_int();

if(n ; return 0; }

int k = read_int();

if(k< 0 || k> = n){std :: cout< Bad index!\\\
; return 0; }

std :: vector< int> v(n)。
return v [k];
}

(我们忽略了向量构造可能抛出异常它自己的。)



道德是C ++中的许多操作是不安全的,只有条件正确,但是程序员希望提前进行必要的检查。语言不会为你做,所以你不付出,但你必须记住这样做。这个想法是,你需要处理错误条件,所以,而不是在库或语言层面执行一个昂贵的,非特定的操作,责任是留给程序员,谁更有能力集成检查



如果我想做一个简单的例子,我会将这种方法与Python进行对比,这样你就可以写出难以置信的和更正程序,而无需任何用户编写的错误处理。另一方面是,任何尝试使用这样的程序,只偏离稍微与程序员打算留下一个非特定的,难以阅读的异常和堆栈跟踪和一些指导你应该做得更好。你不必强制写任何错误处理,并且通常不会写错误处理。 (我不能完全将C ++与Java进行对比,因为虽然Java通常是安全的,但我还没有看到一个 Java程序。)< / rantmode> p>

I am coming from Java and learning C++ in the moment. I am using Stroustrup's Progamming Principles and Practice of Using C++. I am working with vectors now. On page 117 he says that accessing a non-existant element of a vector will cause a runtime error (same in Java, index out of bounds). I am using the MinGW compiler and when I compile and run this code:

#include <iostream>
#include <cstdio>
#include <vector>

int main()
{
    std::vector<int> v(6);
    v[8] = 10;
    std::cout << v[8];
    return 0;
}

It gives me as output 10. Even more interesting is that if I do not modify the non-existent vector element (I just print it expecting a runtime error or at least a default value) it prints some large integers. So... is Stroustrup wrong, or does GCC have some strange ways of compiling C++?

解决方案

The book is a bit vague. It's not as much a "runtime error" as it is undefined behaviour which manifests at runtime. This means that anything could happen. But the error is strictly with you, not with the program execution, and it is in fact impossible and non sensible to even talk about the execution of a program with undefined behaviour.

There is nothing in C++ that protects you against programming errors, quite unlike in Java.


As @sftrabbit says, std::vector has an alternative interface, .at(), which always gives a correct program (though it may throw exceptions), and consequently one which one can reason about.


Let me repeat the point with an example, because I believe this is an important fundamental aspect of C++. Suppose we're reading an integer from the user:

int read_int()
{
    std::cout << "Please enter a number: ";
    int n;
    return (std::cin >> n) ? n : 18;
}

Now consider the following three programs:

The dangerous one: The correctness of this program depends on the user input! It is not necessarily incorrect, but it is unsafe (to the point where I would call it broken).

int main()
{
    int n = read_int();
    int k = read_int();
    std::vector<int> v(n);
    return v[k];
}

Unconditionally correct: No matter what the user enters, we know how this program behaves.

int main() try
{
    int n = read_int();
    int k = read_int();
    std::vector<int> v(n);
    return v.at(k);
}
catch (...)
{
    return 0;
}

The sane one: The above version with .at() is awkward. Better to check and provide feedback. Because we perform dynamic checking, the unchecked vector access is actually guaranteed to be fine.

int main()
{
    int n = read_int();

    if (n <= 0) { std::cout << "Bad container size!\n"; return 0; }

    int k = read_int();

    if (k < 0 || k >= n)  { std::cout << "Bad index!\n"; return 0; }

    std::vector<int> v(n);
    return v[k];
}

(We're ignoring the possibility that the vector construction might throw an exception of its own.)

The moral is that many operations in C++ are unsafe and only conditionally correct, but it is expected of the programmer that you make the necessary checks ahead of time. The language doesn't do it for you, and so you don't pay for it, but you have to remember to do it. The idea is that you need to handle the error conditions anyway, and so rather than enforcing an expensive, non-specific operation at the library or language level, the responsibility is left to the programmer, who is in a better position to integrate the checking into the code that needs to be written anyway.

If I wanted to be facetious, I would contrast this approach to Python, which allows you to write incredibly short and correct programs, without any user-written error handling at all. The flip side is that any attempt to use such a program that deviates only slightly from what the programmer intended leaves you with a non-specific, hard-to-read exception and stack trace and little guidance on what you should have done better. You're not forced to write any error handling, and often no error handling ends up being written. (I can't quite contrast C++ with Java, because while Java is generally safe, I have yet to see a short Java program.)</rantmode>

这篇关于C ++:向量边界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 11:29