分类目录归档:未分类

Chapter 7 Exercises – Professional C++

练习 7-1:分析以下代码片段。列出你能发现的所有问题。您不必在此练习中修复问题;这是练习 7-2 的事。

    const size_t numberOfElements { 10 };
    int* values { new int[numberOfElements] };
    // Set values to their index value.
    for (int index { 0 }; index < numberOfElements; ++index) {
        values[index] = index;
    }
    // Set last value to 99.
    values[10] = 99;
    // Print all values.
    for (int index { 0 }; index <= numberOfElements; ++index) {
        print("{} ", values[index]);
    }

我发现的问题:

  • 内存越界访问,向超出数组最高索引的位置写入值
  • 内存越界访问,数组索引最高为9,却访问索引为10的位置
  • 内存泄漏,使用完动态分配数组后,未释放数组占用的内存

练习 7-2:使用现代且安全的 C++ 构造重写练习 7-1 中的代码片段。

我的解答:

#include <iostream>
#include <memory>
#include <vector>


int main() {
    {
        // 使用智能指针管理 C 风格数组
        const std::size_t numberOfElements{10};
        auto valuesSmartPtr {std::make_unique<int[]>(10)};

        // 将数组元素值设置为索引值
        for (int index{0}; index < numberOfElements; ++index) {
            valuesSmartPtr[index] = index;
        }

        // 设置数组最后一个元素的值为99
        valuesSmartPtr[numberOfElements - 1] = 99;

        // 打印所有值
        for (int index{0}; index < numberOfElements; ++index) {
            std::cout << valuesSmartPtr[index] << " ";
        }
        std::cout << std::endl;
    }

    {
        // 使用 vector
        const std::size_t numberOfElements{10};
        std::vector<int> values;

        // 将数组元素值设置为索引值
        for (int index{0}; index < numberOfElements; ++index) {
            values.push_back(index);
        }

        // 设置数组最后一个元素的值为99
        values.back() = 99;

        // 打印所有值
        for (auto value : values) {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

练习 7-3:编写一个基本类来存储具有 x、y 和 z 坐标的 3-D 点。包括一个接受 x、y 和 z 参数的构造函数。编写一个接受 3-D 点并使用 std::print() 打印其坐标的函数。在您的 main() 函数中,动态分配一个类的实例,然后调用您的函数。

我的解答:

#include <iostream>
#include <memory>

class Point {
public:
    Point(double x, double y, double z) : m_x{x}, m_y{y}, m_z{z} {std::cout << "Point() called!" << std::endl;}
    ~Point() {std::cout << "~Point() called!" << std::endl;}
    double getX() const { return m_x; }
	double getY() const { return m_y; }
	double getZ() const { return m_z; }
private:
    double m_x;
    double m_y;
    double m_z;
};

void printPoint(const Point& point) {
    std::cout << "(" << point.getX() << ", " << point.getY() <<", " << point.getZ() << ")" << std::endl;
}

int main() {
    auto pointPtr {std::make_unique<Point>(1,2,3)};
    printPoint(*pointPtr);  // 传递智能指针指向的对象

    return 0;
}

练习 7-4:在本章前面,以下函数显示在越界内存访问的上下文中。您能使用安全的 C++ 替代方案对该函数进行现代化改造吗?在您的 main() 函数中测试您的解决方案。

    void fillWithM(char* text)
    {
        int i { 0 };
        while (text[i] != '\0') {
            text[i] = 'm';
            ++i;
        }
    }

我的解答:

#include <iostream>
#include <memory>
#include <string>

void fillWithM(std::string& text) {
    for (auto& c : text) {
        c = 'M';
    }
}

int main() {
    std::string t1{"hello world!"};
    
    std::cout << t1 << std::endl;
    fillWithM(t1);
    std::cout << t1 << std::endl;

    return 0;
}